基于Netty的聊天系统(三)协议定制----消息篇

摘要:
今天我们将继续讨论协议。今天,我们基本上定制了一对一的聊天协议。在上一篇文章中,我们描述了登录过程。然后,登录后,我们将聊天。首先,我们将以A和B为例。A向B发送消息,然后消息发送协议如下:{“id”:“xxxx”,“#”:“msg”,“text”:“content”

今天我们继续来讨论协议,今天基本就把一对一聊天的协议定制完毕了,上一篇我们讲述了登录的过程,那么登录完毕就是聊天了,首先我们还是以A和B为例子,A发送消息给B,那么这条消息的的协议如下

发送消息协议:

{"id":"xxxx","#":"msg","text":"内容","to":"接收用户ID","type":0,"msgid":"消息ID"

id:客户端生成的ID

#:不说了,我们之前说过,是对应服务器端的Handler

text:消息内容

to:表示发送给谁

type:表示消息类型

msgid:表示消息的ID

肯定有很多人之后看到之后会有一个问题,我们到底需不需要from 也就是说发送者是谁,其实在这里加上也行,但是其实是不需要的,因为如果既然这个人可以发送消息,那么我们可以在这个人对应的回话里边去存储这个人的信息,所以说只要发送消息,服务器就知道这条消息来自谁,故不需要在这里加from,然后服务器端要响应给该用户是否发送成功,返回的协议,我们在上一篇

auth那里讲述了,用同一个就好了,那么现在服务器如果发现B在线该去通知B来收消息了,那么我们看一下服务器通知B的协议

服务器通知B的协议:

{"id":"xxxx","#":"psh"}

id:服务器生成的id

#:我们这里用了一个psh表示,通知该用户你有新的消息,要获取了,那么B解析到#为psh的时候就应该去请求服务器收消息了 psh=push

B请求服务器收消息协议

{"id":"xxxx","#":"msg-syn"}

id:客户端生成ID

#:对应服务器上的某一个Handler

服务器接收到这个json之后,首先会去从回话中找到B的id,然后去redis中查询聊天信息,多加一句,这里我们存储redis的时候,key值是我们自己订制规则添加的,例如如果B的id为1111

那么我定义的key为user:1111:msg,所以获取消息时候要获取B的id

获取完毕之后,那么我们就可以把消息给B了,那么对应的有一个发送消息的协议格式

发送消息协议:

{"id":"xxxx","fr":"发送用户","text":"内容","time":"消息时间","type":0,"msgid":"消息ID""lv","100"}

id:服务器端生成的id

fr:发送用户

text:消息内容

time:消息时间

type:消息类型

msgid:消息id

lv:这个不太好理解,这是消息的最大score值,可能很多人对score值不清楚,怎么无缘无故冒出来一个这个东西,我们来解释一下,比方说A给B发送消息

那么A如果发送了4条消息,对应的存储应该是:
                   score      value
zset结构:        1        msg1
                        2        msg2
                        3        msg3
                        4        msg4
那么如果用户B来取消息的时候,我们会找到该系列消息,发送给B,然后B接受成功后,返回json字符串,该字符串 ,包含的内容有,是否接受成功,以及最大消息的score值,该值的作用是如果B接受消息成功,我们要把这些消息从,redis中删掉,redis提供了一个根据score进行区间删除的方法我们就可以删掉0--MAX之间的所有消息了,如果还不明白可以去了解一下redis,如果后续有时间,会把进行数据存储的代码贴上来,所以说现在知道我们为什么要获取最大的值了把。

那么在给B发送消息的时候我们并没有结束,当把B所有的消息都给B的时候服务器会在最后再发送一条json数据,这里边包含了是否全部消息都已经发送完毕了,等等信息,如果B接受到该条数据的时候就表示全部收取完毕了,好多朋友会感觉到很不解,为什么最后的这条json里边会包含了是否消息发送完毕的内容,这里我们做个假设,如果B的人气非常火,每天有好多好友给他发消息,那么消息数量会很多,所以当B来去消息的时候我们并不会一下子都把消息给B,假设B有1000个消息,我们可能每次就给B100条,然后在这100条后边加上最后的这个json数据,里边告诉B是否消息已经全部收取了,B可以根据自己的选择来选择是继续获取还是不获取了,主要是做这个使用,那么废话不多说,我们来看看该条协议的定制

{"id":"57968203","#":"msg-ack","remain":0,"lv":["msg":2]}

id:服务器端生成的id

#:msg-ack这是结束表示符,表示这一次消息已经发送完毕

remain:表示是否还有剩余消息0表示消息全部发送完毕,1表示还有消息未读

lv:这里边我们放了一个消息的最大值,其实在这里没有什么含义,客户端在返回的时候还是要把这个值返回来的,用数组的原因是后期可能还有很多别的要放在这里边

客户端收到消息时候会响应服务器端的,协议如下

客户端收到消息响应协议:

{"id":"","#" : "msg-fin","lv" : {"msg" : 2}}

id:不说了

#:msg-fin表示获取消息已经结束了,也就是说B不去获取消息了,

lv:和上边是一样的了,如果实在不懂这个暂时可以忽略掉

那么这么以来一个简单的一对一聊天的协议我们制定完毕了,其实还有很多细节我没有去展示,例如心跳机制,还有例如如果B不在线的时候,B如果上线了要主动去获取一下消息,还有就是检测用户是否更换了手机等等细节,这个大体说一下更换手机这方面,更换手机我们依靠的时候用户手机设备信息然后计算出来一个值,每次去和服务器做对比,这个值什么时候给服务器那,其实在登录成功之后,随便找个空闲时间就可以搞定了,也需要定制一个具体的json协议

免责声明:文章转载自《基于Netty的聊天系统(三)协议定制----消息篇》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇WPF中设置TEXTBOX为多行文本输入框物理像素,ppi,逻辑分辨率和物理分辨率下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

10 TCP限流技术

  TCP限流是因为让接收方充分接受完消息,保证数据安全,不会丢失 一、窗口机制介绍 发送端和接收端都拥有一个窗口,当发送端发送数据时,落进窗口的数据被发送,当接受端接受数据时,落进接收端窗口的数据将会被接受。由此可见可以通过窗口大小限制流量 二、滑动窗口技术(限流使用到的技术) 1 TCP滑动窗口技术通过动态改变窗口大小来调节两台主机间的数据传输。每个T...

总结:MFC中一个对话框的关闭过程 .

说起来挺简单的,一个对话框关闭时要依次调用该类的DestroyWindow-OnDestroy-PostNcDestroy,根据关闭的方法不同,在这些函数之前会调用OnOK、OnCancle或者OnClose。 这里要说的是,模态对话框的消息循环要到调用了PostNcDestroy之后才真正的结束,即ContinueModal循环在这里才结束,然后类的析构...

nc的基本用法

       nc(netcat) 被誉为网络安全界的‘瑞士军刀’,可以用于完成几乎涉及TCP、UDP或者Unix域套接字的任何事。它可以打开TCP连接,发送UDP报文,在任意的TCP和UDP端口监听,进行端口扫描,支持ipv6。不象telnet,nc能够更好地支持脚本,能够将错误消息分离到标准错误,而不是标准输出。nc有四种典型应用: 一、C/S模型 用...

SpringBoot第二十篇:初识ActiveMQ

本文是作者之前写的关于 ActiveMQ 的一篇文章。此处为了保证该系列文章的完整性,故此处重新引入。 一、消息中间件的介绍 介绍 消息队列 是指利用 高效可靠 的 消息传递机制 进行与平台无关的 数据交流,并基于 数据通信 来进行分布式系统的集成。 特点(作用) 应用解耦 异步通信 流量削峰 (海量)日志处理 消息通讯 …... 应用场景 根据消息队...

μC/OS-III---I笔记8---事件标志

   当任务需要同步时可以使用信号量。A任务给B任务发送消息后B任务才能继续运行。如果需要A任务给任务B传递数据的时候就可以采用消息队列。但对于繁杂任务的同步,比如多个时间发生以后执行一个事件,或者是C任务需要任务A和任务B都完成对应的处理任务后才能执行C任务的处理工作,这是用信号量就是等待多个内核对象,有没有一种更好的办法呢,操作系统的大神就创造出了时间...

2.1.1优化程序性能

性能优化有三个层次: 系统层次 算法层次 代码层次 系统层次关注系统的控制流程和数据流程,优化主要考虑如何减少消息传递的个数;如何使系统的负载更加均衡;如何充分利用硬件的性能和设施;如何减少系统额外开销(比如上下文切换等)。 算法层次关注算法的选择(用更高效的算法替换现有算法,而不改变其接口);现有算法的优化(时间和空间的优化);并发和锁的优化(增加任务的...