# XMPP 协议规范

xmpp 是基于 xml 类型进行消息传递的。所有的消息传递类型都是 xmpp 类型的。

![聊天数据流](https://s2.ax1x.com/2019/10/24/KUGlWD.png)

流程：客户端 A 给客户端 B 发送一条消息，消息先从客户端 A 传到服务器，服务器通过判断客户端 B 是否在线，如果在线的就直接把消息推送给客户端 B，客户端 B 收到消息以后，则发送后回执，服务器收到回执以后再推给客户端 A。如果客户端 B 不在线，则消息在服务器端保存，服务器发送回回执告诉客户端 A 发送消息成功，等客户端 B 上线以后再把消息推送给客户端 B。

问题 1: 当客户端 A 给 B 推送消息时，客户端 B 正好此时进入后台。由于后台心跳检测还没有检测到 B 已经离线，这个时候服务器会把消息推送给客户端 B，并且服务器没有保存这条消息。而此时客户端 B 已经进入后台，无法接收到消息，也就无法发送回执。会造成客户端 A 发送消息失败。
解决方法：服务器每次收到客户端 A 都会发送的消息，都会由服务器发送回执告诉 A 已经发送成功。客户端首先保存聊天信息，再客户端 B 是否在线。如果在线，则发送消息，接受回执，如果没有收到回执，则当成不在线，保存聊天消息为未发送状态，下次等客户端 B 连线后推送。

# 消息类型

## 发送消息类型

```xml
<message type="chat" to="110095@domain" id="d851f47818db46b58abf4e982327ab36"><request xmlns="urn:xmpp:receipts"></request><body>{
  "messageId" : "d851f47818db46b58abf4e982327ab36",  //messageid
  "content" : "你好",     //消息内容
  "fromUserName" : "张三",   //发送人
  "isSecret" : 0,      //单聊是否是密聊消息 0:正常聊天  1:密聊
  "timeLen" : 0,
  "isAt" : 0,           //群聊是否@人
  "timeSend" : 1522034423,    //发送时间
  "type" : 1       //消息类型
}</body></message>
```

## 接收消息类型

```xml
<message xmlns="jabber:client" id="cdc6007ca03b401f8c9e4a2ccb75d8d5" type="chat" to="111751@domain" from="109965@domain/resource"><request xmlns="urn:xmpp:receipts"></request><body>{
  "messageId" : "cdc6007ca03b401f8c9e4a2ccb75d8d5",
  "content" : "天津",
  "fromUserName" : "李四",
  "isSecret" : 0,
  "timeLen" : 0,
  "isAt" : 0,
  "timeSend" : 1522034878,
  "type" : 1
}</body></message>
```

## 发送回执消息类型

```xml
<message to="109965@domain/resource" type="chat"><received xmlns="urn:xmpp:receipts" id="cdc6007ca03b401f8c9e4a2ccb75d8d5"/></message>
```

## 接收回执消息类型

```xml
<message xmlns="jabber:client" type="chat" to="111751@domain/resource" from="109965@domain/resource"><received xmlns="urn:xmpp:receipts" id="626b61f461eb485fa99177b69512273e"></received></message>
```
