XMPP 协议
1。 XMPP 优缺点
XMPP (Extensible Messaging and Prence Protocol) (前称Jabber) 是一种以 XML 为基础的开放式即时通讯协议,是经由互联网工程工作小组 (IETF) 通过的互联网标准。[1]
1.1 XMPP 协议的优点
coat什么意思1。1.1 可扩展性
XMPP 的数据传输基于 XML 格式,可扩展性强.XMPP 的核心协议栈 (Core Stack) 部分只定义了基础的 Prence,Message,Iq 等最主要数据格式和传输逻辑,更多的功能则通过定义扩展 (Extensions) 实现.
1.1.2 受 IETF 组织规范
Internet Engineering Task Force (IETF) 在2002年开始规范 XMPP 协议,使其协议的修订和扩展的添加都经过严格的流程审核,防止 XMPP 协议因缺乏标准而分裂.并且这也保证了 XM
PP 协议是完全开放的7755。
1。1。3 应用广泛
XMPP 联系电话的英文协议的应用比其他开放即时通讯协议更为广泛.较有名的使用 XMPP 协议的聊天服务有 Google Gtalk 和 Facebook Chat 等。此外,XMPP 在各平台下都有若干服务端、客户端和程序库的实现,二次开发时成本较低。
XMPP 协议的可扩展性和开放性是该协议被广泛应用的保证。
1。2 XMPP 协议的缺点
genuineness1。2.1 不内置支持二进制数据的传输
XMPP 的核心部分没有包含对二进制数据传输的支持,这使得 XMPP 的基本数据限定在文本文件范围内。XMPP 社区认为,XMPP 应该用于传输 meta 信息,辅助其他应用进行协议握手,XMPP 本身不应负担海量信息的传输。
从当前流行的轻量化观点来看,XMPP 把二进制数据传输的协议移入核心栈,是符合了最
小核心的需求.但同时却为实际应用中 XMPP 客户端传输二进制数据增加了开发扩展协议的负担。
1。2。2 缺乏旗舰应用
XMPP 是开放的,任何个人和组织都可以使用 XMPP.但同时产生的副作用是每个组织使用 XMPP 的目的不同,侧重点不同,导致XMPP 所开发的应用实际上导致了各个厂商各自为政,比如 Cisco 将 XMPP 用于设备通信,游戏厂商用于游戏内的简易聊天。即时通讯中只有 Google Gtalk 和 Fackbook Chat 较出名,但都没有作为这两家企业的核心产品作为推广。 XMPP 的应用中并没有旗舰应用。
XMPP 的缺点归根结底是因为其已经成为开放标准,制定和修改要顾及多方的利益。其核心栈只能包括各种应用的交集部分。各厂商对 XMPP 的利用多会建立一套新的扩展协议以扩展功能,如 Google 用于文件和语音流传输的 Jingle 协议和完全和其他 XMPP 应用不流通的 Google Wave.
但总的来说,XMPP 的问题是一个开放即时通讯协议不可避免遇到的问题。研究 XMPP 协议的实用效果,对将来开放更好的开放协议有重要的参考意义。
2。 XMPP 基础
2。1 网络层次和数据包
XMPP 使用 TCP 连接,并支持安全传输 (TSL/SASL)。
XMPP 的层次结构如下
XMPP
SASL
TSL
TCP
XMPP 层中传输的数据包采用 XML 格式,称为 XML stanzas,权威的意思XMPP 节点间 XML stanzas 的传输构成的数据流称为 XML stream.
一个 XML stream 的概览[2]如下
图一 XML Stream
XMPP 核心栈中,XML stanzas 包括 Prence、Message 和 Iq stanzas。Prence用于传输节点状态,Message 用于传输信息内容,而 Iq 用于传输更复杂的应答。实际应用中,Prence 多限定用于简单的状态传输,而扩展协议多通过扩展 Iq stanzas 元素实现。
2.2 XMPP 的节点与路由
XMPP 中的节点大致有两种,一种是服务器,一种是客户端(暂不讨论各种代理)。客户端需要连接服务器,服务器为客户端提供数据包shenzhou (XML stanzas) 的路由和转发.
图二 XMPP Server—Client 节点
客户端与客户端的通信需要通过服务器中转.每个到达服务器的数据包,由服务器分析后发往别的服务器或客户端。与 Email 的通信机制不同的是,XMPP 服务器之间不设立中转点,而是直接连接,以提高即时性和安全性。
2.3 地址标识
每个客户端需要拥有一个地址标识用于定位,XMPP 中称之为 JID (Jabber ID)。地址标识的格式如下
[ node ”@" ] domain [ "/" resource ]
例如
urname@/pidgin
格式与 Email 地址格式类似,但增添了 resource 项,用于支持同一账号的多客户端登录。上述例子可以解释为:在 gmail。com 服务器注册的 urname 用户,且使用 pidgin 客户端登录。当一个 JID 不包含 resource 部分时,该 JID 一般称为 BareJID.
用户地址标识的认证由提供 XMPP 服务的服务器执行。例如,注册于 gmail 服务器的账号由 gmail 服务器进行验证.其他服务器发往 gmail。com 域名的数据包均通过域名查询与服务间验证后发往 gmail 服务器,而不用考虑 gmail 服务器与下属账号间的通信。
3. XMPP 核心数据包
XMPP 的核心数据包类型有Precen,Message,Iq ,此外加上初始化 stream 用到的 Stream 数据包。这些数据包是 XMPP 信息传输的载体,被用于 XMPP 核心功能和扩展功能的实现。
该部分仅对 XMPP 中使用的数据包进行概览,用于感受基于 XML 的数据包与其他非 XML 数据包协议的差别,不能替代 IETF 关于 XMPP 协议的 RFC 文档 [3920] [3921][3][4],以及 XMPP 的扩展协议文档 [extensions][5] 中描述。
3.1 公有属性
在 XML stream 中,每个数据包都是 XML 格式纯文本。而每个 XML 数据包有以下公有属性:
∙to 数据包要发送的目的地址
∙from 数据包发送的源地址
∙id 数据包标示符
此三项属性在 XML stanza 中最为常见。
to 韩语字母和 from 属性用于服务器决定该数据包的路由规则。某些情况下,to 和 from 属性可以只有一个,例如:客户端向服务端发送设置配置的 Iq 包只含有 to (不向外路由),客户端向联
系人发送 Message 只含有 to (from 属性总是被改写为客户端的地址)。
id 用于节点间判断请求和应答数据包的对应状况,大多数情况可以不处理。
3。2 初始化 XML stream,身份验证
在客户端与服务器产生 TCP 连接后,需要与服务器初始化 XML stream,以及进行身份验证.
初始化时,客户端发送 stream 头部 XML:
<?xmlversion='1.0’?>
〈stream:stream
to=’example。com’
xmlns=’jabber:client’
rescuer xmlns:stream=’http://etherx.jabber。org/streams'
version=’1。0’〉
服务器在收到客户端的 stream 头后,回应一个 stream 头:
<?xmlversion='1.0'?>
〈stream:stream
from='’
id='someid’
xmlns='jabber:client'
xmlns:stream='http://etherx.jabber/streams'
version='1.0'〉
接着服务器向客户端发送服务端支持的身份验证方式列表,常见的方式有基于安全传输 SASL 的 BASE64 编码账户密码验证。身份验证的种类多样,且过程较为繁琐,可以参考《
XMPP: The Definitive Guide》第12章的介绍.
在对话结束时,客户端和服务端要先后发送 stream 尾部 XML,以使整个 XMP stream 闭合。(如果 TCP 异常中断,则服务端直接中断对话)
客户端:
〈/stream:stream>
服务端:
</stream:stream>
3。3 Roster 获取联系人列表
在即时聊天 (IM) 应用中,客户端登录服务器后做的第一个操作通常是获取联系人列表.获取联系人列表需要发送 get 类型的 Iq 数据包。(Iq数据包将会在3。6节解释)
客户端:
<iqfrom行政职务=’juliet@example。com/balcony’type='get’id='roster_1’〉
〈queryxmlns='jabber:iq:roster'/〉
</iq〉
durian该请求的意义为:名为 juliet 的用户 (登录资源为 balcony) 向 服务器请求获得 (get) roster 表。
服务器收到请求后,返回 roster 表。
服务端:
〈iqto='juliet@example。com/balcony’type='result’id='roster_1’〉
〈queryxmlns='jabber:iq:roster'>
〈itemjid='romeo@example。net'
name=’Romeo’
subscription=’both'〉
<group>Friends〈/group>
〈/item〉
〈itemjid=’mercutio@example。org’
name=’Mercutio’
subscription='from’〉
〈group〉Friends</group〉
〈/item>
〈itemjid='benvolio@example。org’
name='Benvolio'
subscription=’both’〉
<group>Friends</group〉