从群聊到私聊:一个Java聊天室的推进

📅 2026/8/1 14:08:51
从群聊到私聊:一个Java聊天室的推进
通信协议对比1.0客户端直接发送“你好”服务端转发xx“你好”2.0群聊客户端发送内容“你好”协议格式2#你好私聊客户端发送内容“小蒲 你好”协议格式1#小蒲#你好通信协议设计客户端——服务端协议发送public void send(String message) { //消息类型 好友名称长度 好友名称 信息类型 消息长度 消息内容 //通过区分是不是私聊 char c1 message.charAt(0); //获取消息的第一个字符 判断是不是 try { OutputStream os socket.getOutputStream(); //输出流 DataOutputStream dos new DataOutputStream(os); if (c1 ) { int index message.indexOf( ); //索引字符位置 String fid message.substring(1, index); //和“ ”之间就是好友名称 substring 截取 String msg message.substring(index 1)来自的account私聊消息; //获取发送者昵称 System.out.println(fid msg); dos.writeInt(1); //私聊 //发送好友名称及消息 依旧长度内容 int fidLen fid.getBytes().length; dos.writeInt(fidLen); dos.write(fid.getBytes()); int msgLen msg.getBytes().length; dos.writeInt(msgLen); dos.write(msg.getBytes()); } else { dos.writeInt(2);//群聊 byte[] msgs message.getBytes(UTF-8); int len msgs.length; dos.writeInt(len); dos.write(msgs); } dos.flush(); } catch (IOException e) { throw new RuntimeException(e); } }用作为私聊标识用1和2区分私聊/群聊用writeInt发送可变长度数据服务端——客户端协议读取转发public String receive(InputStream is,Socket socket){ DataInputStream disnew DataInputStream(is); try { //读取消息类型 私聊1 群聊2 int typedis.readInt(); if(type1){ int fidLendis.readInt(); byte[] fidnew byte[fidLen]; dis.readFully(fid); String fidStrnew String(fid); int msgLendis.readInt(); byte[] msgsnew byte[msgLen]; dis.readFully(msgs); String msgnew String(msgs); System.out.println(收到一条发给fidStr 的私聊消息msg); return 1#fidStr#msg; }else{ int lendis.readInt(); byte[] msgsnew byte[len]; dis.readFully(msgs); String msgnew String(msgs,UTF-8); for (int i 0; i socketList.size(); i) { ClientUser clientUsersocketList.get(i); Socket socket2clientUser.socket; if (socket2socket){ System.out.println(clientUser.accountmsg); } } return 2#msg; } } catch (IOException e) { throw new RuntimeException(e); } }服务端收到后统一用#分隔符封装转发私聊返回格式return 1#fidStr#msg;群聊返回格式return 2#msg;服务端proClientMsg解析时public void proClientMsg(Socket socket){ new Thread(()-{ //登录 //读取用户名 String account proLogin(socket); ClientUser clientUsernew ClientUser(account, socket); //保存clientUser 对象 包含一个socket和一个用户名 socketList.add(clientUser); while (true){ try { InputStream isclientUser.socket.getInputStream(); String msgreceive(is,clientUser.socket); String[] datasmsg.split(#);//通过#将消息拆分成多个片段 变成数组数据 String typedatas[0]; if(type.equals(1)){ String fiddatas[1]; String msg1datas[2]; for (int i 0; i socketList.size(); i) { ClientUser otherCu socketList.get(i); if (otherCu.account.equals(fid)){ send(clientUser.accountmsg1,otherCu.socket.getOutputStream()); break; } } }else{ String msg1datas[1]; for (int i 0; i socketList.size(); i) { ClientUser otherCusocketList.get(i); Socket socket1otherCu.socket; if (socket1!clientUser.socket){ send(clientUser.accountmsg1,socket1.getOutputStream()); } } } } catch (IOException e) { throw new RuntimeException(e); } } }).start(); }PSindexOf(a) //索引字符a位置substring(1,4) //截取字符串中从第二个字符到第五个字符之间的内容split(#) //通过#将消息拆分成多个片段String[] datasmsg.split(#); //将拆分的消息变成数组数据