300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > 韩顺平老师多用户即时通讯系统功能扩展:发送离线消息

韩顺平老师多用户即时通讯系统功能扩展:发送离线消息

时间:2022-02-20 10:03:44

相关推荐

韩顺平老师多用户即时通讯系统功能扩展:发送离线消息

如何实现发送离线消息的功能

思路总结

服务器端思路:

先在接受客户端消息的逻辑块中,先判断接受方是否在线,将其拆分为两种情况,如果对方在线,那么由服务器将消息转发给接收方,如果对方不在线,那么将其加入到一个key为用户id,value为一个消息集合(ArrayList)的离线集合(ConcurrentHashMap)中,当用户登录时判断该用户的id是否存在于该集合的key中,如果存在,那么通过id,获取到对应的消息集合(ArrayList),通过用户id获取到对应的socket,将消息集合发送到客户端

客户端思路:

在客户端的线程中,对接受的object对象使用instance of判断其运行类型,如果为message对象,则进行之前的逻辑,如果为ArrayList对象,则遍历其中所有的message对象,取出内容并打印。

服务器端的新增代码

编写一个OffLineMessageService类 用来处理离线消息####

package qqserver.service;import CommonServerClient.Message;import org.junit.Test;import .util.IPAddressUtil;import java.io.IOException;import java.io.ObjectOutputStream;import java.io.OutputStream;import java.util.ArrayList;import java.util.HashMap;import java.util.concurrent.ConcurrentHashMap;/*** @author 晓宇* @version 1.0* @Time: /7/14 10:31*/@SuppressWarnings({"all"})public class OffLineMessageService {//key->getterId value->contentsprivate static ConcurrentHashMap<String, ArrayList> offlineMap=new ConcurrentHashMap();public static ConcurrentHashMap<String, ArrayList> getOfflineMap() {return offlineMap;}public static void setOfflineMap(ConcurrentHashMap<String, ArrayList> offlineMap) {OffLineMessageService.offlineMap = offlineMap;}@Testpublic void test(){HashMap<String, String> ssHashMap = new HashMap<>();ssHashMap.put("string","hello");System.out.println(ssHashMap.containsKey("string"));}//将离线消息存入到集合中//编写getter不在线 并将离线消息添加到offlineMappublic static void addOfflineMap(Message message){//如果getter不存在 那么创建一个ArrayList 并将message放入if(!offlineMap.containsKey(message.getGetter())){ArrayList<Message> messages = new ArrayList<>();messages.add(message);offlineMap.put(message.getGetter(),messages);}else {ArrayList arrayList = offlineMap.get(message.getGetter());arrayList.add(message);}System.out.println("离线消息已经存放在offlineMap中");}//编写方法判断user是否存在于offlineMap中 如果存在 就获取对应getter的socket 将ArrayList中的所有内容发送public static void sendOfflineMessage(String userId,ConcurrentHashMap offlineMap){if (offlineMap.containsKey(userId)){try {ArrayList<Message> arrayList = (ArrayList<Message>) offlineMap.get(userId);OutputStream os = ManageClientThread.getServerConnectClientThread(userId).getSocket().getOutputStream();ObjectOutputStream oos = new ObjectOutputStream(os);//将message集合发送到客户端oos.writeObject(arrayList);System.out.println("发送成功");} catch (IOException e) {e.printStackTrace();}}else System.out.println("发送失败");}//编写方法判断getter是否在线public static boolean isOnline(String getterId){HashMap<String, ServerConnectClientThread> hm = ManageClientThread.getHm();return hm.containsKey(getterId);}//将离线消息从offlineMap删除public static void deleteOfflineMessage(String getterId){ArrayList remove = offlineMap.remove(getterId);System.out.println("删除消息成功"+remove);}}

在接受客户端消息时 判断接收方是否在线 并将离线消息加入到集合中

if(message.getMesType().equals(MessageType.MESSAGE_COMM_MES)){//写一个方法 判断getter是否在线 不在线的话 将message对象存入到集合中if (!OffLineMessageService.isOnline(message.getGetter())){System.out.println("该用户不在线 将在登录后接受到消息");OffLineMessageService.addOfflineMap(message);}else {//根据message获取getterId 在得到对应的线程ServerConnectClientThread serverConnectClientThread = ManageClientThread.getServerConnectClientThread(message.getGetter());OutputStream outputStream = serverConnectClientThread.getSocket().getOutputStream();ObjectOutputStream oos = new ObjectOutputStream(outputStream);oos.writeObject(message);}

用户登录成功后调用方法发送离线消息

if(checkUser(u.getUserId(),u.getPassword())){//验证通过message.setMesType(MessageType.MESSAGE_LOGIN_SUCCEED);//将message对象回复oos.writeObject(message);//创建一个线程,和客户端保持通讯,该线程持有socket对象ServerConnectClientThread serverConnectClientThread = new ServerConnectClientThread(socket, u.getUserId());serverConnectClientThread.start();//把该线程对象放入到集合中进行管理ManageClientThread.addClientThread(u.getUserId(),serverConnectClientThread);ConcurrentHashMap<String, ArrayList> offlineMap = OffLineMessageService.getOfflineMap();//发送离线消息OffLineMessageService.sendOfflineMessage(u.getUserId(),offlineMap);OffLineMessageService.deleteOfflineMessage(u.getUserId());}else {System.out.println("用户 id=" + u.getUserId() + " pwd=" + u.getPassword() + " 验证失败");message.setMesType(MessageType.MESSAGE_LOGIN_FAIL);oos.writeObject(message);//关闭socketsocket.close();}

客户端新增代码

@Overridepublic void run() {//因为需要在后台和服务器通讯,因此做成while循环while (true){try {System.out.println("客户端线程等待读取服务器端发送的消息");ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());//处理读入的对象Object o = ois.readObject();//如果服务器没有发送objec对象,线程会阻塞在这里if (o instanceof ArrayList){ArrayList<Message> messageArrayList=(ArrayList<Message>)o;System.out.println("以下是您的离线消息:⬇");for (Message message : messageArrayList) {System.out.println(message.getSender()+": "+message.getContent()+" time:");}}else{Message message=(Message)o;//判断message类型 然后做相应的业务处理//如果读取到的式服务得到的返回在线用户列表if (message.getMesType().equals(MessageType.MESSAGE_RET_ONLINE_FRIEND)){//取出在线列表信息,并显示String[] onlineUsers = message.getContent().split(" ");System.out.println("========当前在线用户列表========");for (int i = 0; i <onlineUsers.length ; i++) {System.out.println("用户:"+onlineUsers[i]);}}else if (message.getMesType().equals(MessageType.MESSAGE_COMM_MES)){//普通的聊天消息//把服务端转化的消息显示到控制台即可System.out.println("\n"+message.getSender()+"对"+message.getGetter()+"说"+message.getContent());} else if (message.getMesType().equals(MessageType.MESSAGE_TO_ALL_MES)) {//显示在客户端的控制台System.out.println("\n"+message.getSender()+"对大家说"+message.getContent());}else if (message.getMesType().equals(MessageType.MESSAGE_FILE_MES)){System.out.println("\n"+message.getSender()+"给"+message.getGetter()+"发送文件"+message.getSrc()+"到我的点啊弄目录"+message.getDest());//取出message的字节数组 通过文件输出流写出到磁盘FileOutputStream fileOutputStream = new FileOutputStream(message.getDest());fileOutputStream.write(message.getFileBytes());fileOutputStream.close();System.out.println("\n保存文件成功");}else {System.out.println("是其他类型的message");}}} catch (Exception e) {e.printStackTrace();}}}

第一篇文章 记录学习过程哈 兄弟们都加油

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。