思路分析:
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>();//保存离线用户的messagepublic 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,离线信息有可能是多个.需取出所有messageList<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;}@Overridepublic 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;}
}
如果我写文章您发现有问题,欢迎积极指出.