day03-3私聊功能
多用户即时通讯系统03
4.编码实现02
4.4功能实现-私聊功能实现
4.4.1思路分析
- 客户端 - 发送者:
- 用户在控制台输入信息,客户端接收内容
- 将消息构建成Messgae对象,通过对应的socket发送给服务器
- 服务器:
- 可以读取到客户端(发送者)发送给某个用户(接收者)的消息
- 从管理线程的集合中,根据messgae对象的信息,获取到接收者的userId,从而获取接收者的socket
- 最后将Message对象转发给指定客户(接收者)
- 客户端 - 接收者:
- 在接收者的线程(通信线程中),读取到发送者的message消息,并显示即可
4.4.2代码实现
1.客户端
1.MessageClientService类
这里新建一个类,专门用来管理聊天(私聊/群聊)的功能
package qqclient.service; import qqcommon.Message; import qqcommon.MessageType; import java.io.IOException; import java.io.ObjectOutputStream; import java.util.Date; /** * @author 李 * @version 1.0 * 该类提供和消息(私聊、群聊)相关的服务方法 */ public class MessageClientService { /** * @param content 内容 * @param senderId 发送用户id * @param getterId 接收用户id */ public void sendMessageToOne(String content, String senderId, String getterId) { //构建 message Message message = new Message(); message.setMesType(MessageType.MESSAGE_COMM_MES);//设置消息类型是普通的聊天类型 message.setSender(senderId); message.setGetter(getterId); message.setContent(content); message.setSendTime(new Date().toString());//发送时间也封装到message对象中 System.out.println(senderId + " 对 " + getterId + " 说 " + content); //发送给服务端 try {//在管理线程的集合中,通过userId来获取线程,通过线程来获取对应的socket,再通过socket获取输出流 ObjectOutputStream oos = new ObjectOutputStream(ManageClientConnectServerThread.getClientConnectServerThread(senderId).getSocket().getOutputStream()); oos.writeObject(message); } catch (IOException e) { e.printStackTrace(); } } }
2.修改:ClientConnectServerThread类
在该类的run方法中修改业务代码,增加else if语句
else if (message.getMesType().equals(MessageType.MESSAGE_COMM_MES)) { //接收到的是普通的聊天消息 //就把服务器转发的消息,显示到控制台即可 System.out.println(message.getSendTime() + "\n" + message.getSender() + " 对" + message.getGetter() + " 说" + message.getContent()); }

3.修改处:QQView类
- 在类中增加属性messageClientService
private MessageClientService messageClientService = new MessageClientService();//该对象用于私聊/群聊
- 在类中的内层循环中调用messageClientService对象中的方法

case "3": System.out.println("请输入想聊天的用户号(在线):"); String getterId = Utility.readString(50); System.out.println("请输入想说的话:(100个字符以内)"); String content = Utility.readString(100); //编写一个方法,将消息发送给服务端 messageClientService.sendMessageToOne(content,userId,getterId); break;
2.服务端:
1.修改:ServerConnectClientThread类
- 在该类中增加方法getSocket()
public Socket getSocket() { return socket; }
- 在该类中的run方法中增加私聊的业务代码
else if (message.getMesType().equals(MessageType.MESSAGE_COMM_MES)) { //业务三:客户请求和某用户私聊 //根据message获取getterId,再得到接收者对应的线程 ServerConnectClientThread serverConnectClientThread = ManageClientThreads.getServerConnectClientThread(message.getGetter()); //得到对应的socket的输出流,将message转发给指定的用户 ObjectOutputStream oos = new ObjectOutputStream(serverConnectClientThread.getSocket().getOutputStream()); oos.writeObject(message);//转发消息,提示:如果客户不在线,可以保存消息到数据库,实现离线留言 }
运行:

2.客户端:登录三个用户菩提老祖、至尊宝、紫霞仙子,使其相互通信:
用户1:

用户2:

用户3:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!