【mie haha的博客】转载请注明出处(万分感谢!):
https://blog.csdn.net/qq_40315080/article/details/83052689

用java写聊天室实现群聊很简单,理清思路大概只需15min。

首先分析一下要实现多人的群聊,是要实现什么效果。结合QQ微信,群聊即一个人说一句话,其他所有加入聊天的人都能够收到某某某说了balabala,同时说话的人自己也能够看到自己刚刚说了什么。

接下来考虑在计算机中,两个人聊天是怎么实现信息交互的:并不是两个人直接说话,而是中间有一个“中转站”类似,每个人所说的信息,都先经过这个中转站,再由中转站发出去。(计算机采用这种方式可以方便处理信息,尤其当信息较多较复杂的时候)而这个中转站叫服务器,在java中用Serversocket来声明。每个服务器都需要在一个端口运行,在创建服务器serversocket时应指定它在计算机具体哪个端口运行。(如果不知道端口知识,只需知道这个指定的端口范围只能为1024到49151中即可)每一个连接上服务器的就是聊天的人,即客户端,在java中用socket来声明这个连接。

回到实现群聊:
先创建一个服务器serversocket,接下来创建多个连接实现多个客户端。每个客户端都支持输入语句,假设现在A客户端输入语句B,然后在自己这个客户端输出you said:B,在其他连接的客户端输出A said B。群聊实现。

你会发现以上过程存在两个问题:
1.每个客户端可以说的话(输入)应当没有数量限制,即想输多少条就输多少条。
实现很简单,对每个客户端把输入信息和处理信息写在while(true)循环中即可不断地进 行输入要说的话并群聊输出。
2.可以连接的客户端应当没有数量限制,即想连接几个就连接几个。实现很简单,把生成连接socket写在循环while(true)中即可不停的根据需要产生客户端而不会受到数量限制停止,前面讲大鱼吃小鱼时讲过要实现几个相同又相互独立的对象,将它们用线程实现即可。

现在开始写代码:
先创建服务器,这里我设置运行端口为6666,创建完服务器,用循环不停地产生客户端线程。这里为了实现在群聊中的其他客户端能够看到消息是谁发出的,在创建客户端时用count计数给客户端编号。每个客户端内应包含与服务器的连接,用户名,密码(这里还没涉及到,后面完善代码增加用户登录和注册功能时需要使用),所发出过的所有信息等等。所以需要一个用户User类,来描述客户,而不仅仅只是客户端与服务器的连接socket。所以先写User类,再创建服务器和客户端。

User类实现

public class User {

	//输入的顺序编号
	public int num;
	
	//用户名称
	private String name;
	
	//用户密码
	private String password;
	
	//用户连接
	public Socket socket;
	
	//此人所有消息
	private ArrayList<String> userinforlist = new ArrayList<String>();
	
	public User(Socket socket,String name,String password){
		
		this.socket=socket;
		this.name=name;
		this.password=password;
		
	}
	
	public User(Socket socket,ArrayList<String> userinbforlist,int num){
		
		this.socket=socket;
		this.userinforlist=userinforlist;
		this.num=num;
	}
	
	public void save(String s){
		
		userinforlist.add(s);
	}
	
	public String getname(){
		return name;
	}
	
	public String getpassword(){
		return password;
	}
}

程序开始,先创建服务器,再用while(true)不停创建线程客户端

//创建服务器类,之后在主函数中用该类声明该类的对象
public class sever {

	//一个服务器
	private ServerSocket serverSocket;
	
	//private ArrayList<Socket> socketlist = new ArrayList<Socket>();
	
	//所有客户端
	private ArrayList<User> userlist = new ArrayList<User>();
	
	//在服务器的对话方法中完成在客户端写下信息,捕捉客户端信息,再次在客户端写下信息的功能
	public void talk() {
		
		
		try {
			
			//选择端口创建服务器
			serverSocket = new ServerSocket(6666);
			int count=0;
			//创建使用者列表
			ArrayList<String> userlist = new ArrayList<String>();
			
			//循环创建线程
			while(true){
				
				//连入的用户数+1
				count++;
				//创建连接
				Socket conn = serverSocket.accept();
				
				
		        //创建该连接对应用户所有消息存储
				ArrayList<String> userinforlist = new ArrayList<String>();
				//创建用户
				User user = new User(conn,userinforlist,count);
				//添加用户
				this.userlist.add(user);
				//为用户创建线程
				TTread thread = new TTread(conn,serverSocket,user,this.userlist);
				//线程运行
				thread.start();
			}
			
		} catch (IOException e) {
			
			e.printStackTrace();
		}

	}

	//创建服务器,让服务器开始对话工作
	public static void main(String[] args){
		sever s = new sever();
		s.talk();
	}
}

接下来实现每个客户端输入信息,显示已发消息并发出群聊,每个客户端都是一个线程,所以在线程中来写。(注释掉的代码是还不完善的用来实判断登录是否成功的判断,与群聊实现无关,可以先不看)

public class TTread extends Thread {
	
	//服务器
	private ServerSocket serversocket;
	
    //客户端
	private Socket conn;
	
	//所有客户端信息
	private ArrayList<User> userlist = new  ArrayList<User>();
	//当前客户端
	private User user;

	public TTread(Socket conn,ServerSocket serversocket,User user,ArrayList<User> userlist) {
		
		//当前客户端
		this.conn=conn;
		//服务器
		this.serversocket=serversocket;
		//当前客户端所有信息
		this.user=user;
		//所有用户端
		this.userlist=userlist;
	}

	public void run() {
		
		try {
			
			InputStream filein = conn.getInputStream();
			OutputStream out = conn.getOutputStream();
			BufferedReader reader = new BufferedReader(new InputStreamReader(filein));
			
			out.write("欢迎!\r\n".getBytes());
			out.flush();

			while (true) {

				Handsocket handle= new Handsocket(serversocket, conn, userlist,user);
				
				String guestinformation = reader.readLine();
				
				String type,name,password;
				
				//~前为类型
				//type=guestinformation.split("~")[0];
				//System.out.println(type);
				//~和&间为名字
				//name=guestinformation.split("~")[1].split("&")[0];
				//&后面为密码
				//password=guestinformation.split("~")[1].split("&")[1];
				
				
				//waitcheck wc = new waitcheck(conn,name,password);//创建待检查成员
				//wc.check(type);
			
				out.write(("you said:" + new String(guestinformation)).getBytes());
				out.write(new String("\r\n").getBytes());
				
				
				handle.send_to_all(guestinformation);//发出群聊消息
				
				//用户信息
				user.save(guestinformation);//把消息存入该用户输入的所有信息中

			}
		} catch (FileNotFoundException e) {

			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

}

上面的代码中有一行用来发出群聊消息的代码,接下来对他进行具体实现:

public class Handsocket{

	//当前服务器
	private  ServerSocket socket;
	
	//当前客户端
	
	private Socket thissocket;
	
	//所有客户端
	private ArrayList<User> userlist;
	
	//当前用户
	private User user;
	
	public Handsocket(ServerSocket socket,Socket thissocket,ArrayList<User> userlist,User user){
		
		this.socket=socket;
		this.thissocket=thissocket;
		this.userlist=userlist;
		this.user=user;
	}
	
	//群发消息
	public void send_to_all(String s){
		
		for(int i=0;i<userlist.size();i++){
			
			if(userlist.get(i)!=user){
				
				try{
					
					OutputStream out = userlist.get(i).socket.getOutputStream();
					
					String nnum = ""+user.num;
					
					out.write(nnum.getBytes());
					
					out.write((" said:" + new String(s)).getBytes());
					
					out.write(new String("\r\n").getBytes());
				}
				catch(SocketException e){
					e.printStackTrace();
				}
				catch (IOException e1) {
					e1.printStackTrace();
				} 
			}
		}
		
	}
}

好的现在所有已完全实现。

接下来运行检测一下,检测方法:同时按住Windows键和字母R键,打开“运行”,输入cmd,再输入telnet localhost 6666(6666是以上代码所用的服务器端口)表示连接自己的电脑6666端口,即连接上了代码中的服务器。此时已经生成一个客户端。重复操作可以生成多个客户端。每个客户端都可以输入信息,观察其他客户端的输出情况(当你在一个客户端输入信息,其他客户端有没有输出谁说了什么),检测群聊是否实现。

群聊实现完成。

后面可能会继续出实现聊天室其他功能的文章。

这个版本没有加界面,看起来不太美观,如果需要界面可参考这一篇:https://blog.csdn.net/qq_40315080/article/details/88830295

以上代码全部完整,可直接运行,如有错误或不完善的地方,欢迎指出。

Logo

致力于链接即构和开发者,提供实时互动和元宇宙领域的前沿洞察、技术分享和丰富的开发者活动,共建实时互动世界。

更多推荐