Skip to content
liangchuan edited this page Apr 23, 2014 · 3 revisions

在传统的xmpp服务器上进行扩展,此服务只提供message消息的交换;

使其更轻量及更易于使用,并且服务不再干涉用户以及好友关系管理、聊天室管理等;

更容易集成到现有应用,下文将从 登录、普通聊天与可靠传输、群聊 来介绍系统运行过程。

用户登录

时序图说明:

1. app 用户使用 username/password 向 app 后台的 webapp 提交登录请求,后台返回登录认证的 token; 1. app 用户使用 jid/token 向 ejabberd 服务器发起连接请求,jid=userid@domain,其中userid要求唯一,由小写字母、数字组成; 1. ejabberd服务器回调webapp的token认证接口,验证连接有效性,如果token有效则允许本次连接请求。

普通聊天 与 可靠传输

时序图说明:

1. app_From 为消息发起端,发送 message 给消息服务器; 1. ejabberd 服务器收到消息后给 app_From 回弹一个确认消息,证明消息已经成功到达服务器(下文描述消息格式细节); 1. ejabberd 服务器针对 app_From 发来的 message 建立一个回调任务,如果规定时间没有得到 app_To 反馈则会产生回调; 1. ejabberd 服务器将消息路由到 app_To; 1. app_To 为消息接收端,当收到消息时,要按照下文的协议,给 app_From 回复一个确认消息,证明消息已经成功签收; 1. ejabberd 服务器拦截到app_To的确认消息后,解除回调任务; 1. ejabberd 服务器路由 app_To 的 AckMessage 到 app_From ,完成本次消息递送服务。

所有的交互是建立在 message 基础之上

并且扩展了 message 的 msgtype 属性用来标记各种消息类型,可以按照业务需求任意扩展 msgtype 的值,标识不同类型的消息

系统已占用的 msgtype 属性值如下


* normalchat : 普通聊天消息
* groupchat : 群聊天消息
* msgStatus : 发送的反馈消息,用来同步状态,例如 已读、已接收 等
* serverAck : 服务器主动发送的响应消息

每次发起请求的 message 的 id 属性必须全局唯一,建议使用UUID;

例如:

假设以下场景

app_From 的 jid=userA@test.com

app_To 的 jid=userB@test.com

userA 要向 userB 发送 “hello world” 的普通聊天消息

则有如下交互过程:

1. userA 构建如下消息发送给服务器:


  <message id='xxxx' from='userA@test.com' to='userB@test.com' msgtype='normalchat' type='chat' msgTime='1395475514142' >
      <body>hello world</body>
  </message>

from 属性为 发送人 JID, to 属性为 接收人 JID, msgtype='normalchat' 表示普通聊天消息 msgTime 为 13位正整数 时间戳,此属性必填,标识消息发送时间 特别注意,type='chat' 属性必填,但不代表任何含义。

2. 服务器:收到id=xxxx 的消息后反馈一个消息给 'userA@test.com',证明消息已经到达服务器,如:


  <message id='yyyy' from='messageack@test.com' to='userA@test.com' msgtype='serverAck' type='normal'>
    <body>{'src_id':'xxxx','received':'true'}</body>
  </message>

message的id属性由服务器产生, from 属性的 jid 中的 username 段固定为 messageack, type 固定为 normal,不代表任何含义 msgtype 固定为 serverAck,方便客户端判断此消息类型 message的body节中包含一段json格式的业务信息,其中src_id为 “第1步” 中message消息的ID,表明服务器已经收到了id='xxxx'的消息

3. 服务器将 id='xxxx' 的消息路由到 'userB@test.com';同时监听 userB 反馈的 id='xxxx' 的响应消息,如果5秒内得不到响应, 服务器会产生离线消息回调,通知webapp端,webapp端根据业务需要推送通知给接收者;

4. userB 收到 id='xxxx' 的消息后,做如下回复,响应给发送者,如:


  <message id='xxxx' from='userB@test.com' to='userA@test.com' msgtype='msgStatus' type='normal' msgTime='1395475514142'>
    <body>{'state':'received'}</body>
  </message>

注意:这个响应消息的ID与接收到的消息ID必须相同; msgtype 为 msgStatus 表示发送的是一个ACK响应消息; type 为 normal 必填,但不代表任何含义; body 节中的值,为json格式的结构化数据,由收发双方自定义解析逻辑,此处假设反馈了一个接受状态为“已签收”。

5. 如果第4步没有及时执行,那么当 userB 再次连接服务器时,还会收到此消息,直到 userB 作出响应为止。

6. userA 收到 userB 的响应后,可以根据响应内容,显示消息的不同状态,例如:已接收、已读 等。

以上为可靠传输的交互过程,消息中出现的属性均为必填属性。

群聊天

时序图说明:

1. 用户通过app向webapp获取群信息; 1. app端通过群聊组ID请求webapp端打开一个组; 1. app端向组内发聊天信息,信息中包含组ID(具体消息格式见下文); 1. ejabberd通过组ID向webapp请求获取组成员列表; 1. ejabberd将消息路由到组内每个成员; 1. 当app端为IPHONE用户时,关闭应用后无法保持长连接,所以需要在离线消息时回调webapp,将此类消息发到苹果的推送服务上。

群聊与普通聊天类似,都是用 message 消息完成,其中的目标地址和消息类型有所不同,具体如下:

例如:

假设以下场景

聊天组ID: groupid=g10001

组内成员: userA、userB、userC

userA 向聊天组内发消息 “大家好”

userB、userC 收到来自 g10001 组成员 userA 的消息

有如下交互过程:

1. userA 构建如下消息发送给服务器:


  <message id='xxxx' from='userA@test.com' to='g10001@group.test.com' msgtype='groupchat' type='chat' msgTime='1395475514142' >
      <body>大家好</body>
  </message>

from 属性为 发送人 JID, to 属性遵循 "组ID@group.域" 的结构约定,如 域=test.com 组ID=g10001 则 to=g10001@group.test.com, msgtype='groupchat' 表示群组聊天消息 msgTime 为 13位正整数 时间戳,此属性必填,标识消息发送时间 特别注意,type='chat' 属性必填,但不代表任何含义。

2. 服务器调用“获取群成员接口”接口根据groupid获取组内可接收消息的成员列表,并讲消息路由到每个成员;

3. 组内成员接收群组消息,以成员 userB 为例,会收到如下消息:


  <message id='zzzz' from='userA@test.com' to='userB@test.com' msgtype='groupchat' type='chat' msgTime='1395475514142' groupid="g10001">
      <body>大家好</body>
  </message>

from 属性为 发送人 JID, to 属性为 组内成员 userB 的 JID msgtype='groupchat' 表示群组聊天消息 msgTime 为 13位正整数 时间戳,此属性必填,标识消息发送时间 groupid 属性标记消息来自哪个组

4. 组馁成员收到消息后,必须做出响应,并且区别于普通聊天的响应消息:


  <message id='zzzz' from='userB@test.com' to='g10001@group.test.com' msgtype='msgStatus' type='normal'  msgTime='1395475514142' >
      <body>{'state':'received'}</body>
  </message>

注意:这个响应消息的ID与接收到的消息ID必须相同; msgtype 为 msgStatus 表示发送的是一个ACK响应消息; type 为 normal 必填,但不代表任何含义; body 节中的值,为json格式的结构化数据,由收发双方自定义解析逻辑,此处假设反馈了一个接受状态为“已签收”。 注意:其中 to 属性为聊天群的 JID,而非消息发送人的 JID,此处区别于普通聊天消息。

Clone this wiki locally