韩顺平老师多用户即时通讯系统功能扩展:发送离线消息(只需修改服务器端)

该系统实现了仅修改服务器端代码即可处理离线消息的功能。当用户不在线时,消息存储在服务器,用户上线后通过OfflineMessage类的offline方法遍历并转发离线消息,确保消息的完整性。此设计关键在于判断用户状态和使用ObjectOutputStream转发消息。
摘要由CSDN通过智能技术生成

说明1:只需修改服务器端代码,客户端代码可以不用修改

说明2:离线消息的存储放在了ServerConnectClientThread 中处理私聊消息模块,只需经过一个判断就可以识别是在线消息还是离线消息,从而可以确定是存储还是直接转发

else if (ms.getMesType().equals(MessageType.MESSAGE_COMM_MES)) {
    System.out.println(ms.getSender() + "向" + ms.getGetter() + "发送消息,消息内容保密");
    if (!ManageServerConnectClientThread.hm.containsKey(ms.getGetter())) {
        System.out.println(ms.getGetter() + "暂不在线,将在上线后发送");
        ArrayList<Message> messages = new ArrayList<>();
        if (QQServer.offlineDB.containsKey(ms.getGetter())) {
            QQServer.offlineDB.get(ms.getGetter()).add(ms);
        } else {
            messages.add(ms);
            QQServer.offlineDB.put(ms.getGetter(), messages);
        }
    } else {
        // 此处为关键,获取ms的 getter 的socket
        // getServerConnectClientThread()方法:根据当前的userId,获取对应的线程
        Socket socket1 = getServerConnectClientThread(ms.getGetter()).socket;
        // 本质上为转发
        ObjectOutputStream oos = new ObjectOutputStream(socket1.getOutputStream());
        oos.writeObject(ms);// 如果用户不在线,可以保存到数据库,这样就可以实现留言
    }

}

说明3:用户上线后是否有自己的离线消息相关方法放在了新建类OfflineMessage 中,offline()方法提供遍历集合,离线消息转发功能等功能

public class OfflineMessage {

    public void offline(String userId, Socket socket) {
        // 登录成功后遍历db集合查看是否有离线消息
        // ConcurrentHashMap.KeySetView<String, ArrayList> keySet = offlineDB.keySet();
        // 遍历集合,得到getterId
        ConcurrentHashMap.KeySetView<String, ArrayList<Message>> getterIds = QQServer.offlineDB.keySet();
        for (String getterId : getterIds) {
            if (getterId.equals(userId)) {
                System.out.println("数据库中有用户" + getterId + "的离线消息");
                // 根据userId 取出对应的ArrayList<Message>
                ArrayList<Message> messages = QQServer.offlineDB.get(getterId);
                for (int i = 0; i < messages.size(); i++) {
                    Message message = messages.get(i);
                    try {
                        ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
                        oos.writeObject(message);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
            // 消息转发成功,从数据库中删除消息
            QQServer.offlineDB.remove(getterId);
        }
    }
}

说明4:只需要在用户登录后调用offline()方法即可,注意:一定要在服务器返回用户登录成功消息之后再去调用,不然会出现invalid type code: AC异常

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值