linux多人聊天室是如何实现的?

linux多人聊天室是如何实现的?,第1张

多人聊天室可通过保持网络连接、保持进程运行保持通信。想要自己搭建多人聊天室其实也很简单,你可以直接用ZEGO即时通讯,内置文本、图片、语音、视频、地理位置等各种消息类型,支持单聊、群聊、房间聊天,自由组合IM能力,也可针对自身业务场景,定制所需服务规格。

先去下载咯: http://lumaqq.linuxsir.org/main/?q=node/18 一定要下载最新带JRE版本,我现在用2005都不太好用,所以一直在等2006的正式版,如果使用2005,请千万下载PATH,因为没这个下载好友列表的时候就过不去了第二步就开始安装了:直接在桌面上点击,选择解压到某个目录,然后把把PATCH解压出来的所有jar文件拷贝到LumaQQ的lib目录下覆盖原文件,最后是在桌面上建立个启动项,这个嘛就是桌面点右键选择新建启动项(不同版本不同桌面会叫不同的名字)然后选择个图标,连接上解压目录里的LUMAQQ启动程序就可以了!简单吧!注意:1、如果你的系统是Mac OS X,那么这个lib目录是在"LumaQQ安装目录/LumaQQ.app/Contents/Resources/lib"2、如果出现权限问题或者NoClassDefFoundException,使用chmod -R 777 [安装目录]更改权限。

package API_Day09

import java.io.BufferedReader

import java.io.IOException

import java.io.InputStream

import java.io.InputStreamReader

import java.io.OutputStream

import java.io.OutputStreamWriter

import java.io.PrintWriter

import java.net.ServerSocket

import java.net.Socket

import java.util.HashMap

import java.util.Map

import java.util.concurrent.ExecutorService

import java.util.concurrent.Executors

/**

* 控制台聊天程序

* 服务端应用程序

* @author Jacob

*

*/

public class chatServer

{

/**

* ServerSocket 是运行在服务端的Socket

* 用来监听端口,等待客户端的连接,

* 一旦连接成功就会返回与该客户端通信的Socket

*/

private ServerSocket serverSocket

/**

* 创建线程池来管理客户端的连接线程

* 避免系统资源过度浪费

*/

private ExecutorService threadPool

/**

* 该属性用来存放所有客户端的输出流,用于消息的广播

* private List<PrintWriter>allOut

*/

/**

* 该属性用来存放客户端之间私聊的信息

*/

private Map<String,PrintWriter>allOut

/**

* 构造方法,服务端初始化

*/

public chatServer()

{

try

{

/*

* 创建ServerSocket,并申请服务端口

* 将来客户端就是通过该端口连接服务端程序的

*/

serverSocket = new ServerSocket(12580)

/*

* 初始化Map集合,存放客户端信息

*/

allOut = new HashMap<String, PrintWriter>()

/*

* 初始化线程池,设置线程的数量

*/

threadPool = Executors.newFixedThreadPool(10)

/*

* 初始化用来存放客户端输出流的集合,

* 每当一个客户端连接,就会将该客户端的输出流存入该集合;

* 每当一个客户端断开连接,就会将集合中该客户端的输出流删除;

* 每当转发一条信息,就要遍历集合中的所有输出流(元素)

* 因此转发的频率高于客户端登入登出的频率,

* 还是应该使用ArrayList来存储元素,仅限群聊,私聊不行

* allOut = new ArrayList<PrintWriter>()

*/

}

catch (Exception e)

{

e.printStackTrace()

}

}

/*

* 将客户端的信息以Map形式存入集合中

*/

private void addOut(String key,PrintWriter value)

{

synchronized(this)

{

allOut.put(key, value)

}

}

/*

* 将给定的输出流从共享集合中删除

* 参数为客户端nickName,作为Map的key键

*/

private synchronized void removeOut(String key)

{

allOut.remove(key)

System.out.println("当前在线人数为:"+ allOut.size())

}

/*

* 将给定的消息转发给所有客户端

*/

private synchronized void sendMsgToAll(String message)

{

for(PrintWriter out: allOut.values())

{

out.println(message)

System.out.println("当前在线人数为:"+ allOut.size())

}

}

/*

* 将给定的消息转发给私聊的客户端

*/

private synchronized void sendMsgToPrivate(String nickname,String message)

{

PrintWriter pw = allOut.get(nickname)//将对应客户端的聊天信息取出作为私聊内容发送出去

if(pw!=null)

{

pw.println(message)

System.out.println("当前在线私聊人数为:"+ allOut.size())

}

}

/**

* 服务端启动的方法

*/

public void start()

{

try

{

while(true)

{

/*

* 监听10086端口

*/

System.out.println("等待客户端连接... ... ")

/*

* Socket accept() 这是一个阻塞方法,会一直在10086端口进行监听

* 直到一个客户端连接上,此时该方法会将与这个客户端进行通信的Socket返回

*/

Socket socket = serverSocket.accept()

System.out.println("客户端连接成功! ")

/*

* 启动一个线程,由线程来处理客户端的请求,这样可以再次监听

* 下一个客户端的连接了

*/

Runnable run = new GetClientMsgHandler(socket)

threadPool.execute(run)//通过线程池来分配线程

}

}

catch(Exception e)

{

e.printStackTrace()

}

}

/**

* 该线程体用来处理给定的某一个客户端的消息,循环接收客户端发送

* 的每一个字符串,并输出到控制台

* @author Jacob

*

*/

class GetClientMsgHandler implements Runnable

{

/*

* 该属性是当前线程处理的具体的客户端的Socket

* @see java.lang.Runnable#run()

*/

private Socket socket

/*

* 获取客户端的地址信息

* private String hostIP

*/

/*

* 获取客户端的昵称

*/

private String nickName

/*

* 创建构造方法

*/

public GetClientMsgHandler(Socket socket)

{

this.socket = socket

/*

* 获取远端客户的Ip地址信息

* 保存客户端的IP地址字符串

* InetAddress address = socket.getInetAddress()

* hostIP = address.getHostAddress()

*/

}

/*

* 创建内部类来获取昵称

*/

private String getNickName() throws Exception

{

try

{

//服务端的输入流读取客户端发送来的昵称输出流

InputStream iin = socket.getInputStream()

InputStreamReader isr =

new InputStreamReader(iin,"UTF-8")

BufferedReader bReader = new BufferedReader(isr)

//服务端将昵称验证结果通过自身的输出流发送给客户端

OutputStream out = socket.getOutputStream()

OutputStreamWriter iosw =

new OutputStreamWriter(out,"UTF-8")

PrintWriter ipw = new PrintWriter(iosw,true)

//读取客户端发来的昵称

String nameString = bReader.readLine()

while(true)

{

if(nameString.trim().length()==0)

{

ipw.println("FAIL")

}

if(allOut.containsKey(nameString))

{

ipw.println("FAIL")

}

else

{

ipw.println("OK")

return nameString

}

nameString = bReader.readLine()

}

}

catch(Exception e)

{

throw e

}

}

@Override

public void run()

{

PrintWriter pw = null

try

{

/*

* 通过客户端的Socket获取客户端的输出流

* 用来将消息发送给客户端

*/

OutputStream os = socket.getOutputStream()

OutputStreamWriter osw = new OutputStreamWriter(os,"UTF-8")

pw = new PrintWriter(osw,true)

/*

* 将客户昵称和其所说的话作为元素存入共享集合HashMap中

*/

nickName = getNickName()

addOut(nickName, pw)

Thread.sleep(100)

/*

* 服务端通知所有客户端,某用户登录

*/

sendMsgToAll("[系统通知]:欢迎**"+nickName+"**登陆聊天室!")

/*

* 通过客户端的Socket获取输入流

* 读取客户端发送来的信息

*/

InputStream is = socket.getInputStream()

InputStreamReader isr = new InputStreamReader(is,"UTF-8")

BufferedReader br = new BufferedReader(isr)

String msgString = null

while((msgString = br.readLine())!=null)

{

//验证是否是私聊

if(msgString.startsWith("@"))

{

/*

* 私聊格式:@昵称:内容

*/

int index = msgString.indexOf(":")

if(index >=0)

{

//获取昵称

String name = msgString.substring(1,index)

String info = msgString.substring(index+1,msgString.length())

info = nickName + "对你说:"+ info

//将私聊信息发送出去

sendMsgToPrivate(name, info)

//服务端不在广播私聊的信息

continue

}

}

/*

* 遍历所有输出流,将该客户端发送的信息转发给所有客户端

*/

System.out.println(nickName+"说:"+ msgString)

sendMsgToAll(nickName+"说:"+ msgString)

}

}

catch (Exception e)

{

/*

* 因为Win系统用户的客户端断开连接后,br.readLine()方法读取

* 不到信息就会抛出异常,而Linux系统会持续发送null;

* 因此这里就不在将捕获的异常抛出了。

*/

}

finally

{

/*

* 当执行到此处时,说明客户端已经与服务端断开连接

* 则将该客户端存在共享集合中的输出流删除

*/

removeOut(nickName)

/*

* 通知所有客户端,某某客户已经下线

*/

sendMsgToAll("[系统通知]:"+nickName + "已经下线了。")

/*

* 关闭socket,则通过Socket获取的输入输出流也一同关闭了

*/

if(socket!=null)

{

try

{

socket.close()

}

catch(IOException e)

{

e.printStackTrace()

}

}

}

}

}

public static void main(String[] args)

{

chatServer server = new chatServer()

server.start()

}

}


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/7190814.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-02
下一篇 2023-04-02

发表评论

登录后才能评论

评论列表(0条)

保存