TCP多人聊天室

TCP多人聊天室的实现

1. 功能分析

1.1 客户端
  1. 功能:
    1. 数据发送
    2. 数据接收
  2. 聊天:
    1. 群聊
    2. 私聊
1.2 服务器
  1. 功能:
    1. 数据转发
    2. 用户注册
  2. 数据转发判断:
    1. 私聊
    2. 群聊
      我们需要知道一点:一个用户对应着一个socket,所以我们需要将用户和socket进行绑定,我们可以使用Map来进行存储,Key用来存储用户id,Value用来存储对应的socket

代码

1. 服务器
public class Server{
	private HashMap<Integer, UserSocket> userMap;
	//累计访问人数,作为用户的id(userMap中的Key值)
	private static int count = 0;
	//初始化
	public Server () {
		userMap = new HashMap<>();
	}
	//服务器启动方法
	public void start() throws IOException {
		//启动服务器,监听端口
		ServerSocket serverSocket  = new ServerSocket(8888);
		System.out.println("服务器启动");
		while (true) {
			//接收用户请求
			Socket socket = serverSocket .accept();
			count += 1;
			UserSocket userSocket = new UserSocket(count, socket);
			userMap.put(count, userSocket);
			
			// 启动当前UserSocket服务
			new Thread(userSocket).start();
		}
	}
	class UserSocket implements Runnable {
		private DataInputStream inputstream;
		private DataOutputStream outputStream;
		//用户id
		private int userId;
		//用户名 ,这个是刚开始注册的时候客户端发送给服务器的
		private String userName;
		//连接标记
		private boolean connection;
		
		//构造方法
		public UserSocket(int userId, Socket socket) {
			this.userId = userId;
			try {
				inputStream = new DataInpuStream(socket.getInputStream());
				outputStream = new DataOutputStream(socket.getOutputStream());
				connection = true;
			} catch (IOException e) {
				e.printStackTrace();
				connetion = false;
			}
			try {
				this.userName = InputStream.readUTF();
				//广播所有人XXX上线了,自己除外
				sendOther ("ID:" + this.userId + " " + this.userName + "来到直播间", true);
				send("欢迎来到聊天室");
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		/*
		* 接收客户端发送的数据,用于转发操作
		*/
		public String receive() {
			String msg = null;
			try {
				msg = inputStream.readUTF();
			} catch  (IOException e)  {
				e.printStackTrace();
				connetion = false;
				//设置的工具类,关闭资源
				CloseUtil.closeAll(inputStream, outputStream);
			}
			return msg;
		}
		/*
		* 发送数据到客户端
		*/
		public void send(String msg) {
			try{
				outputStream.writeUTF(msg);
				outputStream.flush();
			} catch (IOException e) {
				e.printStackTrace();
				connetion = false;
				CloseUtil.closeAll(inputStream, outputStream);
			}
		}
		public void sendOther(String msg, boolean sys) {
			//私聊@1:XXXXXX
			if (msg.startsWith("@") && msg.contains(":")) {
				//获取私聊的id
				Integer id = Integer.parseInt(msg.substring(1, msg.indexOf(":")));
				String newMsg = msg.substring(msg.indexOf(":"));

				UserSocket userSocket = userMap.get(id);
				if (userSocket != null) {
					userSocket.send("ID:" + this.userId + " " + this.userName + "悄悄的对你说" + newMsg);
				}
			} else {
				//群聊
				Collection<UserSocket> values = userMap.values();
				for (UserSocket userSocket : values) {
					if (userSocket != this) {
    					// 判断是不是系统消息
    						if (sys) {
        							userSocket.send("系统公告:" + msg);
    						} else {
        							userSocket.send("ID:" + this.userId + " " + this.userName + msg);
   						}
					}
				}
			}
		}
		@Override
		public void run() {
    			while (connetion) {
        			// 使用receive收到的消息作为参数,同时标记非系统消息,调用sendOther
        			sendOther(receive(), false);
   			}
		}
	}
	public static void main (String[] args) {
		Server server = new Server();
		try {
   			server.start();
		} catch (IOException e) {
    			e.printStackTrace();
		}

	}
}
2. 工具类

在这里插入图片描述

3. 客户端
3.1

在这里插入图片描述

3.2 ClientSend
public calss ClientSend implements Runnable {
	private DataOutputStream outputStream;
	
	private BufferedReader console;

	private boolean connection;
	
	public ClientSend(Socket socket, String userName) {
		try {
    			outputStream = new DataOutputStream(socket.getOutputStream());
    			console = new BufferedReader(new InputStreamReader(System.in));
    			
    			send(userName);
    			connection = true;
   		} catch (IOException e) {
    			e.printStackTrace();
    			connection = false;
    			CloseUtil.closeAll(outputStream, console);
		}
	}

	//从键盘上获取用户输入的数据
	public String getMsgFromConsole() {
    		String msg = null;
    		try {
    			// 从键盘上读取一行数据
    			msg = console.readLine();
		} catch (IOException e) {
    			e.printStackTrace();
    			connection = false;
    			CloseUtil.closeAll(outputStream, console);
		}
		return msg;
	}
	//发送数据给服务器
	public void send(String msg) {
		try {
			if (msg != null && !"".equals(msg)) {
				outputStream.writeUTF(msg);
				outputStream.flush();
			}
		} catch  (IOException e) {
			e.printStackTrace();
			connection = false;
			CloseUtil.closeAll(outputStream, console);
		}
	}
	@Override
	public void run() {
    		while (connection) {
        			send(getMsgFromConsole());
   		}
	}
}
3.3 ClientReceive
public class ClientReceive implements Runnable {
	private DataInputStream inputStream;
	private boolean connection;
	public ClientReceive(Socket socket) {
    		try {
        			inputStream = new DataInputStream(socket.getInputStream());
        			connection = true;
    		} catch (IOException e) {
        			e.printStackTrace();
        			connection = false;
    		}
	}
	public void receive() {
		String msg = null;
		try {
    			msg = inputStream.readUTF();
		} catch (IOException e) {
    			e.printStackTrace();
    			connection = false;
   			CloseUtil.closeAll(inputStream);
		}
		System.out.println(msg);
	}
	@Override
	public void run() {
    		while (connection) {
        			receive();
    		}
	}
}
4. 效果

在这里插入图片描述
在这里插入图片描述

发布了29 篇原创文章 · 获赞 30 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_43932553/article/details/104952727