zl程序教程

您现在的位置是:首页 >  其他

当前栏目

day03-3私聊功能

2023-03-31 10:46:18 时间

多用户即时通讯系统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() + "
" + message.getSender()
            + " 对" + message.getGetter() + " 说" + message.getContent());
}
image-20220922220740157
3.修改处:QQView类
  1. 在类中增加属性messageClientService
private MessageClientService messageClientService = new MessageClientService();//该对象用于私聊/群聊
  1. 在类中的内层循环中调用messageClientService对象中的方法
image-20220922221128611
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类
  1. 在该类中增加方法getSocket()
public Socket getSocket() {
    return socket;
}
  1. 在该类中的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);//转发消息,提示:如果客户不在线,可以保存消息到数据库,实现离线留言

} 

image-20220922221423722

运行:

image-20220922215217273

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

用户1:

image-20220922215310105

用户2:

image-20220922215358058 image-20220922215427089

image-20220922215516367

用户3:

image-20220922215626262 image-20220922215658551