OpenFire源码学习之二十四:消息回执与离线消息(上)
2018-02-06 11:19
411 查看
在上一篇提到了4个问题,现在开始回答第三个第四个问题。由于篇幅问题。这里就设置成了上下两篇
这个是第三个问题,如何做消息回执。
消息回执分为两种:
1、普通消息
2、延迟消息
3、离线消息
普通消息
普通消息是客户端正常的点对点发送聊天消息。格式大致如下:
[html] view
plain copy
<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>
客户端接收到系统发送的消息后,应该回执如下内容
[html] view
plain copy
<message id="V4NkR-38" to="8ntmorv1ep4wgcy"
from="test1@8ntmorv1ep4wgcy/Spark 2.6.3#android" type="crs"/>
延迟消息:
延时消息是指,系统推送聊天消息后。接收方没有回执,系统则会把消息返回发送方。这种消息不需要客户端回执。
此消息内容如下:
[html] view
plain copy
<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</<
20000
/span>delay>
</message>
离线消息:
接收方不在线的时候,需要接收到的消息被系统存储。当客户端登陆的时候,推送给接收者。
该消息推送后,需要接收方回执
离线消息内容
[html] view
plain copy
<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说明)
[html] view
plain copy
<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可以不用做回执。所以下面分为系统消息会普通消息
系统消息:
服务端发送者:
[html] view
plain copy
<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>
客户端返回消息接收状态报告
[html] view
plain copy
<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服务端:
[html] view
plain copy
<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消息
[html] view
plain copy
<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客户端在线返回状态
[html] view
plain copy
<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返回消息发送失败)
[html] view
plain copy
<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给出的消息离线
[html] view
plain copy
<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>
客户端返回离线报告
[html] view
plain copy
<message id="p4y4N-38" to="8ntmorv1ep4wgcy"
from="test2@8ntmorv1ep4wgcy/Smack#android" type="crs">
<received xmlns="urn:xmpp:receipts">201</received>
</message>
群组消息
在线
OF发送消息:
[html] view
plain copy
<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>
在线客户端回复:
[html] view
plain copy
<message id="6238-5" to="8ntmorv1ep4wgcy" from="test2@8ntmorv1ep4wgcy"
type="csgo">
<received xmlns='urn:xmpp:receipts'>200</received>
</message>
离线
OF发送消息
[html] view
plain copy
<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:offli
4000
ne" current="2013-11-20T08:28:17.639Z"/>
</message>
新建表结构
ofSysMsgHistory(系统消息历史记录表):
ofGroupOptHistory(个人群组操作历史信息表)
ofTerminalForMsg(消息对应设备已读状态关联表)
ofUserLogin(用户登陆历史信息)
ofClientUpgradeVersion(客户端版本升级表)
ofTerminalInfo(设备信息表)
表关系图:
这个就是几张表之间的关系图了。
下面还有需要修改openfire的jar中的源码,关于tinder部分,本人会单独拿出来写一片博文。在tinder.jar包中 修改Message.Type类型
[java] view
plain copy
/**
* System Upgrade
*/
sug,
/**
* SystemAnnouncement
*/
sp,
/**
* group opt
*/
sgo,
/**
* Businessmessage
*/
spb,
/**
* system time
*/
st,
/**
* Clientsreceiving state
*/
crs;
/**
* 群组操作返回
*/
csgo;
在登陆的时候还需要修改登陆session信息,绑定资源等。
客户端修改绑定资源:
[java] view
plain copy
<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()方法中)
[java] view
plain copy
Bind bindResource = new Bind();
bindResource.setResource(resource);
bindResource.setTerminal("android");
Bind实体中添加相应属性
服务端返回绑定设置:
[html] view
plain copy
<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>
消息回执
这个是第三个问题,如何做消息回执。消息回执分为两种:
1、普通消息
2、延迟消息
3、离线消息
普通消息
普通消息是客户端正常的点对点发送聊天消息。格式大致如下:
[html] view
plain copy
<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>
客户端接收到系统发送的消息后,应该回执如下内容
[html] view
plain copy
<message id="V4NkR-38" to="8ntmorv1ep4wgcy"
from="test1@8ntmorv1ep4wgcy/Spark 2.6.3#android" type="crs"/>
延迟消息:
延时消息是指,系统推送聊天消息后。接收方没有回执,系统则会把消息返回发送方。这种消息不需要客户端回执。
此消息内容如下:
[html] view
plain copy
<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</<
20000
/span>delay>
</message>
离线消息:
接收方不在线的时候,需要接收到的消息被系统存储。当客户端登陆的时候,推送给接收者。
该消息推送后,需要接收方回执
离线消息内容
[html] view
plain copy
<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说明)
[html] view
plain copy
<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可以不用做回执。所以下面分为系统消息会普通消息
系统消息:
服务端发送者:
[html] view
plain copy
<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>
客户端返回消息接收状态报告
[html] view
plain copy
<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服务端:
[html] view
plain copy
<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消息
[html] view
plain copy
<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客户端在线返回状态
[html] view
plain copy
<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返回消息发送失败)
[html] view
plain copy
<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给出的消息离线
[html] view
plain copy
<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>
客户端返回离线报告
[html] view
plain copy
<message id="p4y4N-38" to="8ntmorv1ep4wgcy"
from="test2@8ntmorv1ep4wgcy/Smack#android" type="crs">
<received xmlns="urn:xmpp:receipts">201</received>
</message>
群组消息
在线
OF发送消息:
[html] view
plain copy
<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>
在线客户端回复:
[html] view
plain copy
<message id="6238-5" to="8ntmorv1ep4wgcy" from="test2@8ntmorv1ep4wgcy"
type="csgo">
<received xmlns='urn:xmpp:receipts'>200</received>
</message>
离线
OF发送消息
[html] view
plain copy
<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:offli
4000
ne" 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) | 创建时间 |
字段名 | 类型 | 说明 |
msgId | varchar2(15) | 消息id(主键) |
userId | varchar2(15) | 接受者用户id |
stanza | varchar2(100) | 消息内容 |
creationDate | Char(15) | 创建时间 |
字段名 | 类型 | 说明 |
msgId | varchar2(15) | 消息id(主键) |
userId | varchar2(15) | 用户id(主键) |
TerminalId | varchar2(15) | 设备id(主键) |
字段名 | 类型 | 说明 |
userId | varchar2(15) | 用户id(主键) |
TerminalId | varchar2(15) | 设备id(主键) |
version | varchar2(15) | 最近登陆版本号 |
字段名 | 类型 | 说明 |
version | varchar2(15) | 版本号 |
level | int | 1.重大升级 2.普通升级 |
creationDate | Char(15) | 升级时间 |
字段名 | 类型 | 说明 |
id | int | 设备id |
desc | varchar2(15) | 1.Android 2.Iphone windowsPhone |
这个就是几张表之间的关系图了。
下面还有需要修改openfire的jar中的源码,关于tinder部分,本人会单独拿出来写一片博文。在tinder.jar包中 修改Message.Type类型
[java] view
plain copy
/**
* System Upgrade
*/
sug,
/**
* SystemAnnouncement
*/
sp,
/**
* group opt
*/
sgo,
/**
* Businessmessage
*/
spb,
/**
* system time
*/
st,
/**
* Clientsreceiving state
*/
crs;
/**
* 群组操作返回
*/
csgo;
在登陆的时候还需要修改登陆session信息,绑定资源等。
客户端修改绑定资源:
[java] view
plain copy
<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()方法中)
[java] view
plain copy
Bind bindResource = new Bind();
bindResource.setResource(resource);
bindResource.setTerminal("android");
Bind实体中添加相应属性
服务端返回绑定设置:
[html] view
plain copy
<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>
相关文章推荐
- OpenFire源码学习之二十四:消息回执与离线消息(上)
- OpenFire源码学习之二十四:消息回执与离线消息(上)
- OpenFire源码学习之二十四:消息回执与离线消息(上)
- OpenFire源码学习之二十五:消息回执与离线消息(下)
- OpenFire源码学习之二十五:消息回执与离线消息(下)
- OpenFire源码学习之二十五:消息回执与离线消息(下)
- OpenFire源码学习之二十五:消息回执与离线消息(下)
- openfire服务端消息回执插件(接收方离线时的情况),判断用户的在线状态
- openfire服务端消息回执插件(接收方离线时的情况),判断用户的在线状态
- openfire服务端消息回执插件(接收方离线时的情况),判断用户的在线状态
- OpenFire源码学习之十四:插件管理
- OpenFire源码学习之十四:插件管理
- OpenFire源码学习之三十:haproxy负载均衡
- openfire 保存离线消息
- [学习总结]6、Android异步消息处理机制完全解析,带你从源码的角度彻底理解
- (转)OpenFire源码学习之二十七:Smack源码解析
- Android2.1消息应用(Messaging)源码学习笔记(转载)
- OpenFire源码学习之八:MUC用户聊天室
- OpenFire源码学习之十四:插件管理
- OpenFire源码学习之十四:插件管理