在线用户给离线用户发送消息

在下面代码中,仅仅展示私聊时,在线用户给离线用户发送消息,不考虑群发消息或者文件发送。

因为消息的接收者不在线,所以服务端线程集合里,不存在消息接收者的线程。故而这里会爆一个空指针异常

为了解决这个问题,我们就要在服务端线程里的私聊代码块中判断消息接收者的线程是否存在。

下面的是我修改之后的服务器线程关于私聊的代码块

if (message.getMesType().equals(MessageType.MESSAGE_COME_MES)) {System.out.println(message.getSender()+"发送给" + message.getGetter() + "的消息:"+message.getContent());//得到接收者的输出流,将得到的信息返回if (ManageClientThreads.getServerConnectClientThread(message.getGetter())==null){//假如用户不在线//把消息存放进一个集合里,等到用户登陆时判断集合是否有自己没有接收到的信息,有的话取出来NoOnlineUserMessage.hashMap.put(message.getGetter(),message);}else {ObjectOutputStream objectOutputStream = new ObjectOutputStream(ManageClientThreads.getServerConnectClientThread(message.getGetter()).getSocket().getOutputStream());objectOutputStream.writeObject(message);//加入客户不在线,可以保存到数据库,可以实现离线留言}}

大家可能已经注意到了,我将在线用户发送给离线用户的消息存放进了一个集合里面,之后离线用户上线时,可以通过这个集合来获取自己因为离线而没有收到的消息,我新开了一个类,专门存放这个集合。

集合的key是消息的接收者,也就是离线用户的id,value是消息本身

package QQServer.Service;import QQCommon.Message;import java.util.HashMap;public class NoOnlineUserMessage {public static HashMap<String, Message> hashMap=new HashMap<>();
}

以上就是在线用户给离线用户发送消息的全部了,接下来我将叙述离线用户如何获取集合里的消息

离线用户接收自己离线时的消息

我把这个功能放进了用户的二级菜单里面了

我的二级菜单

System.out.println("============网络通信系统二级菜单============");System.out.println("\t\t 1 显示在线用户列表");System.out.println("\t\t 2 群发消息");System.out.println("\t\t 3 私聊消息");System.out.println("\t\t 4 发送文件");System.out.println("\t\t 5 查看自己离线时没有收到的信息");System.out.println("\t\t 9 退出系统");System.out.println("请输入您的选择:~~~~");

之后在switch函数里的case新加一个判断:

                                case "5":System.out.println("查看自己离线时没有接收到的信息");messageClientService.LookMyNoLookMessage(userID);break;

我把这个LookMyNoLookMessage(String sender)方法写进了发送信息的服务类(MessageClientService)了

LookMyNoLookMessage(String sender):我们定义一个新的消息,我们需要设置消息的类型以及消息的发送者,发送给服务器端。这个消息的主要作用就是将消息的发送者与服务器端的集合的key进行比对,类似于小蝌蚪找妈妈

public void LookMyNoLookMessage(String sender){Message message = new Message();message.setSender(sender);message.setMesType(MessageType.MESSAGE_LOOK_MY_NO_LOOK);try {ObjectOutputStream objectOutputStream = new ObjectOutputStream(ManageClientConnectServerThread.getClientConnectServiceThread(message.getSender()).getSocket().getOutputStream());objectOutputStream.writeObject(message);} catch (IOException e) {e.printStackTrace();}}

需要注意的是,因为这是一个全新的方法,所以我在消息类型里面新定义了一个Type。

以下代码是我的MessageType,类型9就是我新定义的,一定注意,客户端与服务端的MessageType一定要保持一致

package QQCommon;public interface MessageType {//在接口里面定义常量,不同的常量代表不同的消息类型String MESSAGE_LOGIN_SUCCEED = "1";//登录成功String MESSAGE_LOGIN_FAIL="2";//登录失败String MESSAGE_COME_MES="3";//普通信息包String MESSAGE_GET_ONLINE_FRIEND="4";//要求返回用户列表String MESSAGE_RET_ONLINE_FRIEND="5";//返回在线用户列表String MESSAGE_CLIENT_EXIT="6";//客户端要求退出String MESSAGE_GROUP_CHAT="7";//群聊String MESSAGE_SEND_FILES="8";//发送文件String MESSAGE_LOOK_MY_NO_LOOK="9";//查看离线时没有接收到的信息
}

我们调用这个函数之后,服务器端会接收到一个消息,我们对消息的类型进行判断。

遍历集合,找到与发送者一样的key,得到发送者因为离线而没有收到的消息,之后得到发送者的输出流,输出流输出我们在集合找到的message,重新发送给客户端

if (message.getMesType().equals(MessageType.MESSAGE_LOOK_MY_NO_LOOK)){Iterator<String> iterator = NoOnlineUserMessage.hashMap.keySet().iterator();while (iterator.hasNext()) {String next = iterator.next().toString();if (next.equals(message.getSender())){//NoOnlineUserMessage.hashMap.get(next)//这个就是没有接收到的信息ObjectOutputStream objectOutputStream = new ObjectOutputStream(ManageClientThreads.getServerConnectClientThread(next).getSocket().getOutputStream());objectOutputStream.writeObject(NoOnlineUserMessage.hashMap.get(next));}}}

客户端进行接收,并把消息打印到输出台上。

if (message.getMesType().equals(MessageType.MESSAGE_LOOK_MY_NO_LOOK)){System.out.println("这是你离线时没有接收到的信息:");System.out.println("发送者:   " + message.getSender() + '\n' +"接收者:   " + message.getGetter() + '\n' +"发送时间:   " + message.getSendTime() + '\n' +"内容:   " + message.getContent() + '\n');}

代码到这里基本就已经完成了,看看效果吧!

程序效果

大家可以看到,这里只运行了一个客户,在线客户给离线客户发送信息

这是服务器端的情况,可以看到正常,没有报错

之后我们登录用户200,查看离线时自己错过的信息

效果比较理想。

总结

总体思路就是,在线用户给离线用户发送信息,离线用户暂时收不到,我们便把消息放到一个集合里面,之后等离线用户上线后,对服务器端进行示意,表示自己已经上线,就想办法从集合里重新取出自己的消息,之后发给自己。

PS:

我的第一篇博客,如果大家对于这个内容有任何不明白的地方,请私信我,我将尽我全力无偿向大家解答。

韩顺平QQ项目给离线用户发送信息相关推荐

  1. 韩顺平QQ多用户聊天系统-离线消息发送

    将离线文件,离线消息设计为一个离线消息类,实现Runnable 接口,具体代码如下 package QQServer.Service;import qqcommon.Message;import ja ...

  2. java 记录一下韩顺平QQ多用户聊天系统-离线消息发送问题invalid stream header: 7371007E

    参考了很多大佬的资料. 如果有多条留言就会报错: invalid stream header: 7371007E 测试对象输出如下 第一次写入一个B对象  转换成16进制如下 第二次写入二个B对象 多 ...

  3. 微信公众号-根据openID给指定用户发送信息

    微信公众号-给指定用户发送信息 文章目录 微信公众号-给指定用户发送信息 前言 一.开通模板消息 二.项目使用步骤 1.引入库 2.直接上代码 controller service 其他一些封装的类 ...

  4. 微信开发调试小工具进化→微信用户发送信息模拟器发布!——这标题起真是好数码暴龙的说...

    直接说正题吧.最近在做微信第三方服务器.在模拟用户发过来的请求方面,网上流传着一个"微信开发调试小工具",谁做都不知道了.反正我觉得那个东西看起来挺不爽的,因为其信息发送类型不是很 ...

  5. linux上给其他在线用户发送信息(wall, write, talk, mesg)

    linux上给其他在线用户发送信息(wall, write, talk, mesg) 2018-01-05 lonskyMR 转自 恶之一眉 修改 微信分享: 设置登录提示 /etc/motd文件的用 ...

  6. Linux 把文件内容发送给用户,linux上给其他在线用户发送信息(wall, write, talk, mesg)...

    linux上给其他在线用户发送信息(wall, write, talk, mesg) 2018-11-30 设置登录提示 /etc/motd文件的用途 /etc/motd即message of tod ...

  7. asp向不同的用户发送信息_ASP.NET Core 中的那些认证中间件及一些重要知识点

    前言 在读这篇文章之间,建议先看一下我的 ASP.NET Core 之 Identity 入门系列(一,二,三)奠定一下基础. 有关于 Authentication 的知识太广,所以本篇介绍几个在 A ...

  8. asp向不同的用户发送信息_【asp.net core 系列】 1 带你了解一下asp.net core

    0. 前言 这是一个新的系列,名字是<http://ASP.NET Core 入门到实战>.这个系列主讲http://ASP.NET Core MVC,辅助一些前端的基础知识(能用来实现我 ...

  9. asp向不同的用户发送信息_.Net Core 和 .Net Framework的不同

    起因 近期因为公司业务的关系,开始使用.net生态环境,因此对.Net Core和 .Net Framework进行了一些研究. 历史 .Net Framework 历史要比 .Net Core 久一 ...

最新文章

  1. 单片机流星灯_51单片机拖尾灯实现
  2. asp.net 调用带证书的webservice解决办法
  3. python echo和linux交互_Python与shell的3种交互方式介绍
  4. 推荐使用typora
  5. is array php,PHP 源码 — is_array 函数源码分析
  6. java数组显示最大值,java 如何用方法在数组中找到最大值并显示他的名称?
  7. Redis的安装及原理介绍
  8. C++中应用于for循环的auto机制,有引用和非引用两种操作
  9. 117 Populating Next Right Pointers in Each Node II
  10. 2017-2018-1 JAVA实验站 第四、五周作业
  11. opensips(1)——安装opensips详细流程
  12. 杭州电子科技大学计算机网络考研,2017杭州电子科技大学计算机网络考研大纲...
  13. 人工智能、机器学习和模式识别以及神经网络
  14. DATE_FORMAT函数用法
  15. 标志寄存器FLAGS----小总结
  16. 全球便携式电源行业调研及趋势分析报告
  17. win10导入iphone手机中的照片和视频出错:发生了一些问题,文件可能未导入
  18. Spire.XLS:一款Excel处理神器
  19. 在Unity中使用四叉树算法绘制地形
  20. Linux课程笔记 硬盘介绍及硬盘分区

热门文章

  1. 【C#】winform 图片局部放大类似淘宝
  2. Policy Gradient Theorem Explained-视频总结笔记(待续。。)
  3. vue使用自定义字体LcdD液晶字体
  4. 李开复博士写给中国大学生的 信
  5. SAP配置——MRP
  6. 扫普通链接二维码打开小程序
  7. 论文分享 |《DeepCluster》
  8. 春松客服:通过开源加云原生模式,大规模交付智能客服系统 | Chatopera
  9. MATLAB基本常识知识总结
  10. 搜索引擎核心技术与算法 —— 倒排索引