韩顺平JAVA多用户通讯系统多用户离线留言部分

思路分析:

1.服务器接收到a用户传递给b用户的message

2.服务器从在线用户列表里面寻找b用户id

3.如果没找到就保存a用户发送来的message,否则就直接发送过去

4.b用户上线发送给服务器一个离线信息请求

5.服务器判断是否有b用户的离线信息
服务器找到b用户的离线信息,就发送过去,服务器没找到就新建一个离线信息类型的message,发送给b用户

6.b用户收到服务器返回的离线信息
如果是正常(私聊,文件)信息就正常显示,如果是离线类型的message就输出一句"没有您的离线信息"

思路分析流程图:

在这里插入图片描述

具体代码

客户端代码

客户端UserClienServuce类里面


public static void Check_for_offline_information(String uid)
  {

    Message message = new Message();

    message.setSender(user.getUserId());
    message.setMessageType(MessageType.MESSAGE_GET_OFFLINE_INFORMATION);//新添加的一个message类型

    try {
      ObjectOutputStream oos = new ObjectOutputStream(
              MangerClientConnectSeverThread.
                      getClientConnectSeverThread(uid).getSocket().getOutputStream());
      oos.writeObject(message);

    } catch (IOException e) {
      e.printStackTrace();
    }
  }

调用位置

这里是调用的位置

服务器代码

服务器端代码新建的一个db类


package com.wjh.qqSever.server;

import com.wjh.qqcommon.Message;
import com.wjh.qqcommon.MessageType;

import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Set;

/**
 * @author <wjh>
 * @version:1.0 2023/3/20
 */
public class db {
    private static HashMap<String, List<Message>> offlineusers = new HashMap<>();
    private static List<Message> offmessage = new ArrayList<Message>();
    
    //保存离线用户的message
    public static saveofflineinformation(String rid, Message message) {
        if (offlineusers.containsKey(rid)) {
            offlineusers.get(rid).add(message);
        } else {
            List messages = new ArrayList<>();
            messages.add(message);
            offlineusers.put(rid, messages);
        }

    }
    /**
     * 发送服务器存储的该uid的离线信息
     * 发送之后删除该uid的离线信息
     */
    public static void sendofflinemessages(String uid) {
        Set<String> keySet = offlineusers.keySet();
        for (String id :
                keySet) {
            if (id.equals(uid)) {
                try {
                    //取出该uid的list,离线信息有可能是多个.需取出所有message

                    List<Message> list = getOfflineusers().get(uid);
                    for (int i = 0; i < list.size(); i++) {
                        ObjectOutputStream oos = new ObjectOutputStream(MangeClientThreads.getClientThread(uid).getSocket().getOutputStream());

                        oos.writeObject(list.get(i));
                    }
                    offlineusers.remove(uid);
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }
            else
            {
                Message message = new Message();
                message.setMessageType(MessageType.MESSAGE_RET_OFFLINE_INFORMATION);
                try {
                    ObjectOutputStream oos = new ObjectOutputStream(MangeClientThreads.getClientThread(uid).getSocket().getOutputStream());
                    oos.writeObject(message);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }

    public static HashMap<String, List<Message>> getOfflineusers() {
        return offlineusers;
    }
    

}


因为判断接收者是否在线是服务器来判断的,我在SeverConnectClientThread这个类里面进行判断的

package com.wjh.qqSever.server;

import com.wjh.qqcommon.Message;
import com.wjh.qqcommon.MessageType;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.HashMap;
import java.util.List;
import java.util.Set;

/**
 * @author <wjh>
 * @version:1.0 2023/3/10
 * 该类是服务器和客户端保持一个通讯
 */
public class SeverConnectClientThread extends Thread {
    private final String id;
    private final Socket socket;

    public SeverConnectClientThread(String id, Socket socket) {
        this.id = id;
        this.socket = socket;
    }

    @Override
    public void run() {
        while (true) {
            try {
                ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
                Message message = (Message) ois.readObject();
                if (message.getMessageType().equals(MessageType.MESSAGE_GET_ONLINE_FRIEND)) {
                    System.out.println(message.getSender() + "用户需要在线列表菜单");
                    Message message1 = new Message();
                    String onlineFriend = MangeClientThreads.getOnlineFriend();
                    message1.setMessageType(MessageType.MESSAGE_RETURN_ONLINE_FRIEND);
                    message1.setContent(onlineFriend);
                    message1.setReceiver(message.getSender());

                    ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
                    oos.writeObject(message1);

                } else if (message.getMessageType().equals(MessageType.MESSAGE_CLIENT_EXIT)) {
                    System.out.println("用户" + message.getSender() + "退出系统");
                    MangeClientThreads.delClientThread(message.getSender());
                    socket.close();
                    break;
                } else if (message.getMessageType().equals(MessageType.MESSAGE_COMM_MES)) {
//这里判断接收者是否在线,在线就直接发送否则就保存起来
                    SeverConnectClientThread clientThread = MangeClientThreads.getClientThread(message.getReceiver());
                    if (clientThread==null)
                    {
                        db.saveofflineinformation(message.getReceiver(),message);
                    }
                    else {
                        ObjectOutputStream oos = new ObjectOutputStream(clientThread.getSocket().getOutputStream());
                        oos.writeObject(message);
                    }



                } else if (message.getMessageType().equals(MessageType.MESSAGE_MASS_MESSAGEING)) {

                    Set<String> keySet = MangeClientThreads.getHashMap().keySet();

                    for (String id :
                            keySet) {
                        if (!(id.equals(message.getSender()))) //避免发送群聊的用户接受到自己发送的群聊信息
                        {
                            SeverConnectClientThread severConnectClientThread = MangeClientThreads.getHashMap().get(id);
                            ObjectOutputStream oos = new ObjectOutputStream(severConnectClientThread.socket.getOutputStream());

                            oos.writeObject(message);
                        }
                    }


                } else if (message.getMessageType().equals(MessageType.MESSAGE_FILE)) {
                    //这里判断接收者是否在线,在线就直接发送否则就保存起来
                    SeverConnectClientThread clientThread = MangeClientThreads.getClientThread(message.getReceiver());
                    if (clientThread==null)
                    {
                        db.saveofflineinformation(message.getReceiver(),message);
                    }
                    else {
                        try {
                            ObjectOutputStream oos = new ObjectOutputStream(MangeClientThreads.getClientThread(message.getReceiver()).getSocket().getOutputStream());

                            oos.writeObject(message);
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }


                }
                //这里接收客户端发送的离线信息请求
                else if (message.getMessageType().equals(MessageType.MESSAGE_GET_OFFLINE_INFORMATION))
                {
                    db.sendofflinemessages(message.getSender());
                }

                else {
                    System.out.println("其他用户的messa,暂时不处理");
                }
            } catch (IOException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }

        }
    }

    public Socket getSocket() {
        return socket;
    }
}

如果我写文章您发现有问题,欢迎积极指出.

  • 9
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值