当前位置: 首页 > news >正文

从群聊到私聊:一个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 dis=new DataInputStream(is); try { //读取消息类型 私聊1 群聊2 int type=dis.readInt(); if(type==1){ int fidLen=dis.readInt(); byte[] fid=new byte[fidLen]; dis.readFully(fid); String fidStr=new String(fid); int msgLen=dis.readInt(); byte[] msgs=new byte[msgLen]; dis.readFully(msgs); String msg=new String(msgs); System.out.println("收到一条发给"+fidStr +"的私聊消息:"+msg); return "1"+"#"+fidStr+"#"+msg; }else{ int len=dis.readInt(); byte[] msgs=new byte[len]; dis.readFully(msgs); String msg=new String(msgs,"UTF-8"); for (int i = 0; i < socketList.size(); i++) { ClientUser clientUser=socketList.get(i); Socket socket2=clientUser.socket; if (socket2==socket){ System.out.println(clientUser.account+":"+msg); } } 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 clientUser=new ClientUser(account, socket); //保存clientUser 对象 包含一个socket和一个用户名 socketList.add(clientUser); while (true){ try { InputStream is=clientUser.socket.getInputStream(); String msg=receive(is,clientUser.socket); String[] datas=msg.split("#");//通过#将消息拆分成多个片段 变成数组数据 String type=datas[0]; if(type.equals("1")){ String fid=datas[1]; String msg1=datas[2]; for (int i = 0; i < socketList.size(); i++) { ClientUser otherCu = socketList.get(i); if (otherCu.account.equals(fid)){ send(clientUser.account+":"+msg1,otherCu.socket.getOutputStream()); break; } } }else{ String msg1=datas[1]; for (int i = 0; i < socketList.size(); i++) { ClientUser otherCu=socketList.get(i); Socket socket1=otherCu.socket; if (socket1!=clientUser.socket){ send(clientUser.account+":"+msg1,socket1.getOutputStream()); } } } } catch (IOException e) { throw new RuntimeException(e); } } }).start(); }


PS:indexOf('a') //索引字符a位置

substring(1,4) //截取字符串中从第二个字符到第五个字符之间的内容

split("#") //通过#将消息拆分成多个片段

String[] datas=msg.split("#"); //将拆分的消息变成数组数据

http://www.jsqmd.com/news/1307373/

相关文章:

  • LCD、OLED与调光技术全解析:从原理到嵌入式开发实战
  • Hive数据仓库核心架构、部署与性能调优实战指南
  • 15.6英寸便携双屏搭建全攻略:接口选型、系统配置与硬件避坑指南
  • Python实现迅雷链接转换工具:原理、代码与避坑指南
  • AI写作爆文拆解实战手册(附23个真实失败案例复盘):从提示词失效到平台限流的全链路归因
  • 合肥中鼎科技堆垛机应用:丹佛斯 FC360 双闭环矢量控制技术解析
  • 2026济南古钱币银元回收就来毓典奢品汇18617962974全国连锁专业靠谱 - 丽坤奢品汇
  • BGP联邦实战:企业网络架构与排错指南
  • ESP32-S3驱动2.8寸触摸屏:硬件解析、LVGL移植与物联网UI开发实战
  • 选择重传协议(SR)详解:滑动窗口、核心机制与GBN对比
  • 树莓派双通道CAN HAT实战:从硬件拆解到工业网关应用
  • 三级数据库技术-第七章考点详解
  • STM32驱动4英寸电阻屏实战:FSMC+NT35510+XPT2046全解析
  • 被 DDoS 攻击的一夜
  • MiniMax H3 深度解析:打破模态界限,全能多模态模型优势在哪
  • GO Markets:从公开信息出发,拆解移动端体验与长期一致性
  • Unity车辆物理系统实战:基于WheelCollider的赛车插件集成与调优
  • 央行等九部门联合发文,科技金融可信数据空间全面试点!
  • ESP32-S3-Tiny硬件方案解析:低成本物联网核心板设计与实践
  • 广州企业搬迁30条注意事项与避坑清单(2026年最新版行政负责人必读) - 优企甄选
  • Windows蓝牙驱动革命:BthPS3如何让PS3控制器在Windows上完美工作
  • 2026年全国新能源继电器优质厂家推荐实用指南 - 奔跑123
  • 【直流技术的迭代直流照明系统】应用场景
  • SpringBoot @RequestBody接收字符串:原理、场景与避坑指南
  • Jetson Nano边缘AI开发实战:从硬件解析到TensorRT模型部署优化
  • 【锁3】Semaphore(信号量)
  • 树莓派双通道RS485 HAT设计:从SC16IS752芯片到工业数据采集实战
  • 新手部署 OpenClaw 避坑指南,路径设置与安全软件兼容要点(含安装包)
  • C++元编程异构词典:基于策略模式实现类型安全的累加器设计
  • 2026浦江县空调拆装公司推荐,家具拆装公司哪家好?4个坑+5条硬标准,帮你绕开90%的坑 - geo88