OpenFire源码学习之二十四:消息回执与离线消息(上)

来源:互联网 发布:灌砂法压实度试验算法 编辑:程序博客网 时间:2024/05/05 05:07

在上一篇提到了4个问题,现在开始回答第三个第四个问题。由于篇幅问题。这里就设置成了上下两篇

消息回执

这个是第三个问题,如何做消息回执。

消息回执分为两种:

1、普通消息

2、延迟消息

3、离线消息

 

普通消息

普通消息是客户端正常的点对点发送聊天消息。格式大致如下:

<message id="V4NkR-38" type="chat" to="test1@8ntmorv1ep4wgcy/Spark 2.6.3#android" Form="test2@8ntmorv1ep4wgcy/Spark 2.6.3#android"  ><body>.......</body></message>

客户端接收到系统发送的消息后,应该回执如下内容

<message id="V4NkR-38" to="8ntmorv1ep4wgcy"  from="test1@8ntmorv1ep4wgcy/Spark 2.6.3#android" type="crs"/>

延迟消息:

延时消息是指,系统推送聊天消息后。接收方没有回执,系统则会把消息返回发送方。这种消息不需要客户端回执。

此消息内容如下:

<message id="HncqL-52" to="user1@8ntmorv1ep4wgcy/Spark 2.6.3#user11387952379387" from="8ntmorv1ep4wgcy" type="error"><body>{"time":"2013-12-25T14:20:01 032Z","sd":"sd"}</body><delay xmlns="urn:xmpp:delay" current="2013-12-25T14:20:31 038Z">501</delay></message>

离线消息:

接收方不在线的时候,需要接收到的消息被系统存储。当客户端登陆的时候,推送给接收者。

该消息推送后,需要接收方回执

离线消息内容

<message id="HncqL-65" to="1aaa@8ntmorv1ep4wgcy" from="user1@8ntmorv1ep4wgcy/Spark 2.6.3" type="chat">  <body>{"time":"2013-12-25T14:25:43 963Z","sd":"sd"}</body>  <offline xmlns="urn:xmpp:offline" current="2013-12-25T06:26:45.501Z"/></message>

客户端回执规范(需要添加离线namespace说明)

<message id="V4NkR-38" to="8ntmorv1ep4wgcy"  from="test1@8ntmorv1ep4wgcy/Spark 2.6.3#android" type="crs"><offline xmlns="urn:xmpp:offline"/></message>

这里面的type类型crs也是本人做的XMPP拓展了。

对于消息回执本人有两种解决方案。

首先看下消息回执的处理流程图吧:


呵呵,画的很丑。

方案一:

将不同设备的终端标志存储起来,谁读过一个的消息,记录他的设备id。当他再次登陆不同设备的时候,从数据库查找它没有读过的记录。这里计较绕口。但是本人并不推崇,这里主要是提供一个思路。

OK,首先来看个图。本人画得并不好

时序图:


哈哈~又画的很丑

根据本人在项目中的业务情况。比较重要的系统消息(第三方系统发送的消息)需要做回执。普通chat可以不用做回执。所以下面分为系统消息会普通消息

系统消息:

服务端发送者:

<message id="gJE6T-2" to="600788@8ntmorv1ep4wgcy" from="8ntmorv1ep4wgcy">  <body>{"optType":"add","groupId":"testroomta100","groupName":"test房间100","subject":"我是主题","description":"测试","admin":"600788","userList":"600788,test1","msgType":10001}</body></message>

客户端返回消息接收状态报告

<message from='600788@8ntmorv1ep4wgcy'id='gJE6T-2' type=’chat’to=''><received xmlns='urn:xmpp:receipts' type=200/></message>


OpenFire与客户端消息交互内容示例:

聊天消息:

1、在线(模拟client A、B对话)。

A发送消息给Of服务端:

<message id="V4NkR-38" to="test2@8ntmorv1ep4wgcy/Spark 2.6.3"            from="test1@8ntmorv1ep4wgcy/Spark 2.6.3" type="chat">  <body>       {"time":"2013-11-20T06:41:36.102Z",       "cnt":"你想说什么呢?","msgTypec":"10000","mtype":"0"}  </body>  <thread>P2J5R2</thread></message>

Of服务端返回A消息

<message id="V4NkR-38" to="test1@8ntmorv1ep4wgcy/Spark 2.6.3#android"        from="8ntmorv1ep4wgcy"     type="crs">     <body>          {"time":"2013-11-20T06:42:23.761Z","msgType":"10013"}     </body></message>

B客户端在线返回状态

<message id="V4NkR-38" to="8ntmorv1ep4wgcy" from="test2@8ntmorv1ep4wgcy/Spark 2.6.3"          type="crs">     <received xmlns="urn:xmpp:receipts">200</received></message>

B客户端不在线(等待10s,OF给A返回消息发送失败)

<message id="V4NkR-38" to="test1@8ntmorv1ep4wgcy/Spark 2.6.3#android"          from="8ntmorv1ep4wgcy" type="error">     <body>           {"time":"2013-11-20T06:58:58.558Z","cnt":"你想说什么呢?",            "msgTypec":"10000","mtype":"0"}     </body>     <delay xmlns="urn:xmpp:delay" current="2013-11-20T07:05:44.445Z">          501     </delay></message>


2、OF给出的消息离线

<message id="p4y4N-38" to="test2@8ntmorv1ep4wgcy" from="test1@8ntmorv1ep4wgcy/Spark          2.6.3" type="chat">     <body>           {"time":"2013-11-20T07:17:17.816Z","cnt":"你想说什么呢?           ","msgTypec":"10000","mtype":"0"}      </body>  <thread>h3P0lk</thread>  <offline xmlns="urn:xmpp:offline" current="2013-11-20T07:36:24.363Z"/></message>

客户端返回离线报告

<message id="p4y4N-38" to="8ntmorv1ep4wgcy"          from="test2@8ntmorv1ep4wgcy/Smack#android" type="crs">  <received xmlns="urn:xmpp:receipts">201</received></message>


群组消息

在线

OF发送消息:

<message id="2859-1" to="test2@8ntmorv1ep4wgcy" from="8ntmorv1ep4wgcy" type="sgo">     <body>        {"optType":"add","groupId":"BBC0","time":"2013-11-20T08:16:40.214Z",         "groupName":"test房间0","subject":"我是主题",         "description":"测试","admin":"test2",         "userList":"test2,test1","msgType":10001}     </body></message>
在线客户端回复:

<message id="6238-5" to="8ntmorv1ep4wgcy" from="test2@8ntmorv1ep4wgcy"        type="csgo">     <received xmlns='urn:xmpp:receipts'>200</received></message>

离线

OF发送消息

<message id="8954-6" to="test1@8ntmorv1ep4wgcy" from="8ntmorv1ep4wgcy" type="sgo">  <body>       {"optType":"add","groupId":"BBCAD0",        "time":"2013-11-20T08:24:30.583Z","groupName":"test房间0",        "subject":"我是主题",        "description":"测试",        "admin":"test2","userList":"test2,test1","msgType":10001}   </body>  <offline xmlns="urn:xmpp:offline" current="2013-11-20T08:28:17.639Z"/></message>

新建表结构

ofSysMsgHistory(系统消息历史记录表):

字段名

类型

说明

msgId

varchar2(15)

消息id(主键)

mtype

varchar2(10)

消息类型(级别):

0、系统升级(SUG),

1、系统公告(SP),

1、群组操作(SGO),

2、聊天消息(CHAT),

4、业务消息(SPB)

stanza

varchar2(200)

消息内容

creationDate

Char(15)

创建时间

ofGroupOptHistory(个人群组操作历史信息表)

字段名

类型

说明

msgId

varchar2(15)

消息id(主键)

userId

varchar2(15)

接受者用户id

stanza

varchar2(100)

消息内容

creationDate

Char(15)

创建时间

ofTerminalForMsg(消息对应设备已读状态关联表)

字段名

类型

说明

msgId

varchar2(15)

消息id(主键)

userId

varchar2(15)

用户id(主键)

TerminalId

varchar2(15)

设备id(主键)

ofUserLogin(用户登陆历史信息)

字段名

类型

说明

userId

varchar2(15)

用户id(主键)

TerminalId

varchar2(15)

设备id(主键)

version

varchar2(15)

最近登陆版本号

ofClientUpgradeVersion(客户端版本升级表)

字段名

类型

说明

version

varchar2(15)

版本号

level

int

1.重大升级

2.普通升级

creationDate

Char(15)

升级时间

ofTerminalInfo(设备信息表)

字段名

类型

说明

id

int

设备id

desc

varchar2(15)

1.Android

2.Iphone

windowsPhone

表关系图:

这个就是几张表之间的关系图了。

下面还有需要修改openfire的jar中的源码,关于tinder部分,本人会单独拿出来写一片博文。在tinder.jar包中 修改Message.Type类型

     

   /**         * System Upgrade         */        sug,               /**         * SystemAnnouncement         */        sp,               /**         * group opt         */        sgo,               /**         * Businessmessage         */        spb,               /**         * system time         */        st,               /**         * Clientsreceiving state         */        crs;      /**         *  群组操作返回         */        csgo;

在登陆的时候还需要修改登陆session信息,绑定资源等。

客户端修改绑定资源:

<iq id="use1D-4" type="set">    <bind xmlns="urn:ietf:params:xml:ns:xmpp-bind">         <resource>Smack</resource>         <terminal>android</terminal>    </bind></iq>

(smack源码修改地址:类SASLAuthentication中bindResourceAndEstablishSession()方法中)

Bind bindResource = new Bind();        bindResource.setResource(resource);        bindResource.setTerminal("android");Bind实体中添加相应属性

服务端返回绑定设置:

<iq type="result" id="use1D-4" to="8ntmorv1ep4wgcy/2c133c9e">      <bind xmlns="urn:ietf:params:xml:ns:xmpp-bind">            <jid>test1@8ntmorv1ep4wgcy/Smack#android</jid>      </bind></iq>
2 1
原创粉丝点击