XMPP(eXtensible Messaging Presence Protocol,可扩展消息处理和现场协议),是一种用来在两个地点之间传递小型的结构化数据段的协议。
XMPP已被用来构建大规模即时通信系统、Internet游戏平台、搜索引擎、语音、视频会议系统。大多数社交媒体构造(Facebook、MySpace、Twitter)也是采用XMPP协议。
以下内容是对Jack Moffitt的《XMPP高级编程——使用JavaScript和jQuery》的读书笔记。
1 XMPP网络
1.1 服务器
服务器的任务为XMPP节点提供路由。XMPP服务器总是允许用户连接到自己。
1.2 客户端
客户端必须向XMPP服务器进行身份验证,服务器将该客户端发送的所有节路到适当的目的地,服务器还负责管理客户端会话的其他方面,比如花名册、裸地址
2 XMPP寻址
XMPP网络上的每个实体都有一个或多个地址(JID、Jabber identifier),例如:zx0006@192.168.5.128/Strophe是一个完整JID,zx0006@192.168.5.128是裸JID
JID由三部分组成:节点、域(必须的)、资源。
3 XMPP节
3.1 message节
message节用来从一个实体向另一个实体发送消息。message节属于“发射后不管”型,没有内在的可靠性。一旦消息发出去,发送者并不知道它是否传送出去以及何时送达。
<message xmlns="jabber:client" to="zx0006@192.168.5.128" from="oubo6wn5yppl_az_djkdjdoi5utg@192.168.5.128/Strophe" type="chat" isFirst="true">
<body>用户张三接入了</body>
<name>张三</name>
<sessionId>160913953831545548</sessionId>
<stop></stop>
</message>
3.1.1 消息类型
message节点的类型,由type属性定义,可选值为:chat、error、normal、groupchat、headline。
chat:一对一聊天对话上下文中发送。它是哪些关注私有的、一对一通信的IM应用程序最常见的类型。
error:在答复某条错误的消息
groupchat:用于多人聊天中发送的消息。它用来区分多人聊天参与者发送的定向的私有消息与参与者发送给聊天室中所有的广播消息。
headline:哪些不希望或不支持应答的自动化服务使用。如果自动生成的电子邮件携带type属性,那么它的值将使用headline值。
normal:这个类型实际很少使用。
3.1.2消息内容
message节可以包含任意扩展元素。
3.2 IQ节
iq节表示的是Info/Query(信息与查询),它与XMPP通信提供请求与相应机制,每个id节都必须有一个响应。
<iq xmlns="jabber:client" type="result" id="766f772d-edf9-490f-8e49-1ac09a869f3b:ping" from="oubo6wn5yppl_az_djkdjdoi5utg@192.168.5.128" to="zx0006@192.168.5.128/Strophe"></iq>
3.3 presence节
presence节控制并报告实体的可访问性,“在线”、“离线”、“离开”、“请勿打扰”等场景,presence还用于建立和终止向其他实体发布出席订阅
当一方可以进行通信时,另一方有必要获知该情况
4 连接生命周期
4.4 断开连接
当用户结束XMPP会话时,首先先发送无效出席信息,然后关闭<stream:stream>
元素。通过发送最后的无效出席信息,用户的联系人能够得知该用户离开的原因,显式地关闭流则可以让任何在路上的XMPP节安全到达
disconnect: function (reason) {
this._changeConnectStatus(Strophe.Status.DISCONNECTING, reason);
Strophe.info("Disconnect was called because: " + reason);
if (this.connected) {
var pres = false;
this.disconnecting = true;
if (this.authenticated) {
pres = $pres({
xmlns: Strophe.NS.CLIENT,
type: 'unavailable'
});
}
// setup timeout handler
this._disconnectTimeout = this._addSysTimedHandler(
3000, this._onDisconnectTimeout.bind(this));
this._proto._disconnect(pres);
} else {
Strophe.info("Disconnect was called before Strophe connected to the server");
this._proto._abortAllRequests();
}
}