Java聊天室——实现多人聊天、私聊、群聊


客户端

package project.java;
//客户端
//输入、输出流分别为处于一个线程

import java.io.IOException;
import java.io.PrintStream;
import java.net.Socket;
import java.util.Scanner;

class OutToServer2 implements Runnable{
	private Socket client;
	
	public OutToServer2(Socket client) {
		super();
		this.client = client;
	}

	@Override
	public void run() {
		PrintStream printStream;
		try {
			printStream = new PrintStream(client.getOutputStream(),true);
			Scanner scanner = new Scanner(System.in);
			scanner.useDelimiter("\n");
			while(true) {
				System.out.println("请输入:");
				while(scanner.hasNext()) {
					String string = scanner.nextLine();
					printStream.println(string);
					if(string.equals("拜拜")) {
						System.out.println("客户端退出");
						printStream.close();
						scanner.close();
					    //client.close();
						break;
					}
				}
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
}

class ReadFromServer2 implements Runnable{
	private Socket client;
	public ReadFromServer2(Socket client) {
		super();
		this.client = client;
	}
	public void run() {
		try {
			Scanner scanner = new Scanner(client.getInputStream());
			scanner.useDelimiter("\n");
			while(scanner.hasNext()) {
				System.out.println("服务器端输入:"+scanner.nextLine());
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}
	
}

public class SingelClient2 {
	public static void main(String[] args) {
		String serverName = "127.0.0.1";
		int port = 6666;
		Socket client;
		try {
		    client = new Socket(serverName,port);
			Thread ouThread = new Thread(new OutToServer2(client));
			Thread inThread = new Thread(new ReadFromServer2(client));
			ouThread.start();
			inThread.start();
		} catch (Exception e) {

			e.printStackTrace();
		} 
	}
} 

服务器端

package project.java;

import java.io.IOException;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
//服务器端
/**
 * Map<String,Socket>
 * 用户注册:username:yyy
 * 群聊:G:hello
 * 私聊:P:yyy-hhh
*/

class  ExcuteClientServer1 implements Runnable{
	private Socket client;
	private Map<String,Socket> clientMap;
	public ExcuteClientServer1(Socket client, Map<String, Socket> clientMap) {
		super();
		this.client = client;
		this.clientMap = clientMap;
	}

	public void run() {
		try {
			//拿到客户端输入流,读取用户信息
			Scanner scanner = new Scanner(client.getInputStream());
			String string = null;
			while(true){
				if(scanner.hasNext()) {
					string = scanner.nextLine();
					Pattern pattern = Pattern.compile("\r\n|\r|\n");
					Matcher matcher = pattern.matcher(string);
					string = matcher.replaceAll("");
					//用户注册
					if(string.startsWith("user")) {
						//获取用户名
						String useName = string.split("\\:")[1];
						userRegist(useName, client);
						continue;
					}
					//群聊
					else if(string.startsWith("G")) {
						String message = string.split("\\:")[1];
						gropChat(message);
						continue;
					}
					//私聊
					else if(string.startsWith("P")) {
						String temp = string.split("\\:")[1];
						//取得用户名
						String useName = temp.split("\\-")[0];
						//取得消息内容
						String message = temp.split("\\-")[1];
						privateChat(useName, message);
						continue;
					}
					//用户退出
					else if(string.contains("拜拜")) {
						//先根据Socket知道用户名
						String useName = getUseName(client);
						System.out.println("用户名为"+useName +"的用户下线了!!!");
						clientMap.remove(useName);
						continue;
					}
				} 
			}
		}catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	//获取key值(即由端口号找到用户名)
	public String getUseName(Socket socket) {
		String useName = null;
		for(String getKey : clientMap.keySet()) {
			if(clientMap.get(getKey).equals(socket)) {
				useName = getKey;
			}
		}
		return useName;
	}
	//注册实现
	public void userRegist(String useName,Socket client) {
		System.out.println("用户姓名为:" + useName);
		System.out.println("用户socket为:" + client);
		System.out.println("用户名为"+ useName +"的用户上线了!");
		System.out.println("当前用户数为:"+ (clientMap.size()+1) +"人");
		clientMap.put(useName, client);
	}
	//群聊实现
	public void gropChat(String message) {
		Iterator<Entry<String, Socket>> iterable = clientMap.entrySet().iterator();
		for(Map.Entry<String, Socket> stringSocketEntry:clientMap.entrySet()) {
			try {
				Socket socket = stringSocketEntry.getValue();
				PrintStream printStream = new PrintStream(socket.getOutputStream(),true);
	            System.out.println("用户说"+message);	
	            printStream.println(message);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		}
	}
	//私聊实现
	public void privateChat(String useName,String message) {
		//根据对应的useName找到对应的Socket
		Socket privateSocket = clientMap.get(useName);
		try {
			PrintStream printStream = new PrintStream(privateSocket.getOutputStream());
			printStream.println("用户名为"+getUseName(client)+"的用户对你说:"+message);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

public class SingleServer2 {
	public static void main(String[] args) throws IOException {
		ServerSocket serverSocket = new ServerSocket(6666);
		//存取用户信息(用户名和Socket)
		Map<String, Socket> map = new HashMap<String, Socket>();
		//线程池,线程大小为20
		ExecutorService executorService =Executors.newFixedThreadPool(20);
		System.out.println("等待客户连接中...");
			try {
				for(int i = 0;i < 20;i ++) {
				Socket socket = serverSocket.accept();
				System.out.println("有新的用户连接:"+socket.getInetAddress()+socket.getPort());
				executorService.execute(new ExcuteClientServer1(socket,map));
				}
				executorService.shutdown();
				serverSocket.close();
			} catch (Exception e) {
		}
	}
}

  • 57
    点赞
  • 324
    收藏
    觉得还不错? 一键收藏
  • 39
    评论
实现聊天室中的私聊功能,我们可以借助于Java Socket编程和多线程技术来完成。下面是一个简单的实现方法: 1. 客户端和服务器都需要分别创建一个Socket对象,用来建立与服务器的连接。 2. 客户端连接服务器后,可以先发送一个特殊命令,告诉服务器自己的身份,比如私聊ID。 3. 服务器端在接收到客户端连接请求后,将客户端Socket对象保存到一个集合中,以便随时获取和操作。 4. 客户端在选择私聊对象时,将私聊对象的ID和消息内容封装成一个自定义的消息对象,并通过Socket发送给服务器端。 5. 服务器端收到私聊消息后,解析出私聊对象的ID和消息内容。 6. 服务器端根据私聊对象的ID,从保存客户端Socket对象的集合中找到对应的Socket对象。 7. 通过私聊对象的Socket对象,将消息发送给对应的客户端,完成私聊功能。 8. 客户端在接收到服务器发送的私聊消息后,将其展示给用户。 需要注意的是,为了实现多人私聊的功能,服务器端需要维护一个用来保存连接的集合,并对这个集合进行同步操作,以确保在多线程环境下能正确处理私聊请求。 此外,为了更好地用户体验,可以为客户端和服务器端的交互添加一些错误处理、输入验证等功能。 总而言之,通过使用Java Socket编程和多线程技术,我们可以相对轻松地实现聊天室私聊功能。以上是一个简单的实现方法,根据实际需求和具体情况,还可以对其进行进一步的优化和扩展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 39
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值