2023年7月20日发(作者:)
XMPP 协议
1。 XMPP 优缺点
XMPP (Extensible Messaging and Presence Protocol) (前称Jabber) 是一种以 XML 为基础的开放式即时通讯协议,是经由互联网工程工作小组 (IETF) 通过的互联网标准。[1]
1.1 XMPP 协议的优点
1。1.1 可扩展性
XMPP 的数据传输基于 XML 格式,可扩展性强.XMPP 的核心协议栈 (Core Stack) 部分只定义了基础的 Presence,Message,Iq 等最主要数据格式和传输逻辑,更多的功能则通过定义扩展 (Extensions) 实现.
1.1.2 受 IETF 组织规范
Internet Engineering Task Force (IETF) 在2002年开始规范 XMPP 协议,使其协议的修订和扩展的添加都经过严格的流程审核,防止 XMPP 协议因缺乏标准而分裂.并且这也保证了 XMPP 协议是完全开放的。
1。1。3 应用广泛
XMPP 协议的应用比其他开放即时通讯协议更为广泛.较有名的使用 XMPP 协议的聊天服务有 Google
Gtalk 和 Facebook Chat 等。此外,XMPP 在各平台下都有若干服务端、客户端和程序库的实现,二次开发时成本较低。
XMPP 协议的可扩展性和开放性是该协议被广泛应用的保证。
1。2 XMPP 协议的缺点
1。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 包括 Presence、Message 和 Iq stanzas。Presence用于传输节点状态,Message 用于传输信息内容,而 Iq 用于传输更复杂的应答。实际应用中,Presence 多限定用于简单的状态传输,而扩展协议多通过扩展 Iq stanzas 元素实现。
2.2 XMPP 的节点与路由
XMPP 中的节点大致有两种,一种是服务器,一种是客户端(暂不讨论各种代理)。客户端需要连接服务器,服务器为客户端提供数据包 (XML stanzas) 的路由和转发.
图二 XMPP Server—Client 节点
客户端与客户端的通信需要通过服务器中转.每个到达服务器的数据包,由服务器分析后发往别的服务器或客户端。与 Email 的通信机制不同的是,XMPP 服务器之间不设立中转点,而是直接连接,以提高即时性和安全性。
2.3 地址标识
每个客户端需要拥有一个地址标识用于定位,XMPP 中称之为 JID (Jabber ID)。地址标识的格式如下
[ node ”@" ] domain [ "/" resource ]
例如
username@/pidgin
格式与 Email 地址格式类似,但增添了 resource 项,用于支持同一账号的多客户端登录。上述例子可以解释为:在 gmail。com 服务器注册的 username 用户,且使用 pidgin 客户端登录。当一个 JID 不包含 resource 部分时,该 JID 一般称为 BareJID.
用户地址标识的认证由提供 XMPP 服务的服务器执行。例如,注册于 gmail 服务器的账号由 gmail 服务器进行验证.其他服务器发往 gmail。com 域名的数据包均通过域名查询与服务间验证后发往 gmail 服务器,而不用考虑 gmail 服务器与下属账号间的通信。
3. XMPP 核心数据包
XMPP 的核心数据包类型有Precense,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’
xmlns:stream=’http://。org/streams'
version=’1。0’〉
服务器在收到客户端的 stream 头后,回应一个 stream 头:
〈stream:stream
from='’
id='someid’ xmlns='jabber:client'
xmlns:stream='http:///streams'
version='1.0'〉
接着服务器向客户端发送服务端支持的身份验证方式列表,常见的方式有基于安全传输 SASL 的
BASE64 编码账户密码验证。身份验证的种类多样,且过程较为繁琐,可以参考《XMPP: The Definitive
Guide》第12章的介绍.
在对话结束时,客户端和服务端要先后发送 stream 尾部 XML,以使整个 XMP stream 闭合。(如果
TCP 异常中断,则服务端直接中断对话)
客户端:
〈/stream:stream>
服务端:
3。3 Roster 获取联系人列表
在即时聊天 (IM) 应用中,客户端登录服务器后做的第一个操作通常是获取联系人列表.获取联系人列表需要发送 get 类型的 Iq 数据包。(Iq数据包将会在3。6节解释)
客户端:
〈queryxmlns='jabber:iq:roster'/〉 该请求的意义为:名为 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'〉 〈/item〉 〈itemjid=’mercutio@example。org’ name=’Mercutio’ subscription='from’〉 〈group〉Friends 〈/item> 〈itemjid='benvolio@example。org’ name='Benvolio' subscription=’both’〉 〈/iq> 可以看到,juliet 的 roster 表内有3个联系人,分别名为 Romeo,Mercutio,Benvolio,都属于 Friends 分组。Roster 列表中的 JID 信息将会用在稍候客户端发送信息包的目的地址中。 Item 中的 subscription 关系到联系人状态信息的传输,有 none,both,from,to 四种。详细的 subscription 操作在 RFC 3921 Managing Subscriptions章节[7]中定义。 3.4 Presence 状态数据包 Presence 数据包被设计用来发送轻量级的节点状态信息,例如 IM 中用来发送用户的在线、离开、忙碌、离线等简单的状态消息. 一个 presence 数据包范例如下: 客户端: 〈show〉away〈/show> 〈/presence> 该 presence 向服务端表明,客户端用户处于离线状态。服务端收到 presence 后,会自行填充 from 和 to 属性,发送到订阅 (subscribeb) 了该用户状态信息的联系人服务器上. Presence 数据包也可以在发送时填上 to 属性,用于指定 presence 的接收方。例如: 客户端: 〈presenceto="romeo@example。net”> 〈show〉away 该 Presence 只会被转发至 romeo@. 3。5 Message 信息数据包 Message 是即时聊天应用中最常用的数据包,其功能是发送用户聊天信息。一个 Message 例子如下: 客户端: to='romeo@’ from='juliet@/balcony’ type=’chat' xml:lang='en'> 该 message 包将会被服务器转发至 服务器,随后转交给 romeo 已登录的客户端上(如果该用户没有登录,message 信息会储存在服务端直至用户上线)。 其中,body 标签中包含用户要传输的聊天信息。 要传输格式化的富文本信息,可以通过支持扩展XEP—0071[8],引入 html 标签。 3。6 Iq 数据包 Iq 是一个为其他操作提供 get,result,set,error 动作的数据包,本身并没有限定用途的范围。核心协议中就有大量需要用到 Iq 数据包的操作,例如添加 roster 联系人,需要用到 set 类型的 Iq 数据包: 客户端: 〈iqfrom='juliet@example。com/balcony'type='set'id='roster_2'〉 〈queryxmlns=’jabber:iq:roster’> 〈itemjid='nurse@example。com' name=’Nurse’〉 〈/iq> 服务器用 result 类型的 Iq 数据包返回操作结果: 服务端: 〈iqto=’juliet@/balcony'type='result’id='roster_2’/> XMPP 扩展协议大都通过扩展 Iq 数据包的元素来添加操作。Iq 数据包的 type 属性就像 HTTP 协议中的 Method 项一样,提供增删改查 (CURD) 动作,具体实现何种操作并不限制。 4。 XMPP 扩展 XMPP 的核心部分是一个轻量级的协议,不足以满足一般即时聊天应用的需求。 XMPP 的社区在核心协议的基础上定义了众多的扩展协议,用以实现电子名片、二进制传输等功能。 4.1 通过 vcard-temp 获取电子名片 电子名片 (个人资料) 是聊天程序中常见的功能。通过电子名片,用户可以查看联系人除了 JID 地址外的其他信息,如:昵称,全名,个人网站 URL 等. XMPP 的扩展之一 [XEP—0054] vcard-temp [9] 实现了电子名片。要在聊天程序中支持电子名片,需要客户端和服务端都实现 vcard-temp 扩展.知名的 XMPP 服务器大都支持 vcard—temp 扩展,如 , gtalk 等。 4。1。1 请求电子名片 vcard-temp 扩展规定的电子名片访问规则如下: 客户端: id=’v3’ to=’jer@’ type='get'〉 〈vCardxmlns=’vcard—temp'/> 〈/iq〉 该查询使用 get 类型的 Iq 包请求 jabber。org 服务器返回 jer 用户的 vcard 数据。 接着 服务器返回 jer 用户的 vcard 数据: 服务器: 〈iqfrom='jer@jabber。org’ to='stpeter@jabber。org/roundabout' type=’result' id=’v3'> 〈FN〉JeremieMiller 〈GIVEN>Jeremie〈/GIVEN> 〈FAMILY〉Miller〈/FAMILY> 〈JABBERID〉jer@〈/JABBERID〉 〈/iq> vcard-temp 中定义了大量数据项,以上的示例只返回了用户已设置的部分数据项。 4.1。2 隐私问题 目前为止,vcard-temp 扩展被定义为无须经过授权访问,即非好友用户也可以获取任何一个 XMPP 用户的所有 vcard 信息。因此,vcard-temp 扩展建议用户慎重考虑是否要填入个人地址等隐私信息。 4.2 通过 In—Band Bytestreams 传输二进制数据 XMPP 核心部分没有提供二进制数据传输的支持,而 XMPP 扩展中有若干提供二进制传输的协议。应用较广的有 [XEP-0047] In-Band Bytestreams [10] 和 [XEP-0065] SOCKS5 Bytestreams [11]。由于实际上被广为应用二进制传输协议就只有这两种,所以客户端能做的选择不多。In-Band Bytestreams 和 SOCKS5 Bytestreams 可被整合为 [XEP-0096] SI File Transfer [12],这个协议允许接收端选择传输方式。 此外还有 Google 提出的 Jingle 传输协议,Jingle 支持的网络连接方式更多,目前被应用于 Gtalk 客户端上,用于支持二进制文件传输与语音通信的实现,但并未普及。 4。2.1 In—Band Bytestreams 原理 所谓 In-Band ,即为 “在 XMPP 流内”的意思,其完整意义为:将二进制数据置入 XMPP 流内传输.但 XMPP 流的内容是纯文本,如何传输二进制数据呢?In—Band Bytestreams 的方案是把二进制数据使用 Base64 编码转换成可打印的纯文本,然后当作纯文本塞入 Iq 或者 Message 数据包中传输。 4.2。2 In-Band Bytestreams 示例 In—Band Bytestreams 的流程包括发起、接受/拒绝,分包传输,结束应答这几个过程,详细的流程示例参照 [XEP—0047] [10] 中的定义。 一个发送 In-Band Bytestreams 的 Iq 数据包示例如下: 〈iqfrom=’romeo@/orchard’ id=’kr91n475’ to=’juliet@capulet。com/balcony' type=’set'> qANQR1DBwU4DX7jmYZnncmUQB/9KuKBddzQH+tZ1ZywKK0yHKnq57kWq+RFtQdCJ WpdWpR0uQsuJe7+vh3NWn59/gTc5MDlX8dS9p0ovStmNcyLhxVgmqS8ZKhsblVeu IpQ0JgavABqibJolc3BKrVtVV1igKiX/N7Pi8RtY1K18toaMDhdEfhBRzO/XB0+P AQhYlRjNacGcslkhXqNjK5Va4tuOAPy2n1Q8UUrHbUd0g+xJ9Bm0G0LZXyvCWyKH kuNEHFQiLuCY6Iv0myq6iX6tjuHehZlFSh80b5BVV9tNLwNR5Eqz1klxMhoghJOA 〈/data> 〈/iq〉 其中,data 段内包含的字符串是经过 Base64 编码的二进制数据。可见,该二进制数据经过编码后被当作一般纯文本来传输.data 段的 seq 属性标明了此段数据在所有数据分包中的编号。 4。2。3 In—Band Bytestreams 缺陷 In—Band Bytestreams 借助 XMPP 流进行二进制传输,优点是可以稳定交付,只要双方客户端仍然连接各自的服务器就能实现二进制传输.但其重大缺陷是速率过慢,每段二进制数据都要经过分包和多次封包解包,并且每个数据包都通过两个服务器的交付处理,会产生很大的延迟,效率很低。后文有对 In-Band Bytestreams 的简单速率测试。*未完成* 4。3 通过 SOCKS5 Bytestreams 传输二进制数据 4。3.1 SOCKS5 Bytestreams 原理 有别于 In-Band Bytestreams 流内传输,SOCKS5 Bytestreams 方案使用双方客户端的 socks5 直连传输,这样可以使传输速率达到双方主机直连的速度。 SOCKS5 Bytestreams 在传输过程的起效部分仅是让双方客户端决定传输方案,交换 IP 地址,端口地址等信息。当双方客户端决定可以使用的 IP 地址和端口地址后,就发起 socks5 连接,此时 XMPP 流不再参与数据传输,不增加额外的传输延迟. 整个 SOCKS5 Bytestreams (S5B) 流程如图三所示: 图三 XMPP 发起 SOCKS5 Bytestreams 流程 4.3.2 SOCKS5 Bytestreams 示例 一个发起 SOCKS5 Bytestreams 的 Iq 数据包示例如下: 〈iqfrom=’requester@/foo’ id='hu3vax16' to=’target@example。org/bar’ type=’set'> sid=’vxf9n471bn46'〉 〈streamhost jid='requester@example。com/foo' host=’192.168。4。1' port=’5086'/> 〈/query> 〈/iq〉 其中 streamhost 包含了发起人可用的 IP 地址,这个 IP 地址可以是主机地址,也可以是 socks5 代理主机地址 (用于突破防火墙和 NAT 网络的限制)。streamhost 项可以有多个,最终由接收方选择可用的地址,然后发起连接。 4。3。4 SOCKS5 Bytestreams 局限 由于互联网连接的复杂性,发起传输请求的 XMPP 客户端可能只拥有内网 IP ,并且没有可用的 socks5 代理服务器可用.这种情况下发起人将无法实现二进制文件的传输。 并且即使有代理服务器,由于经过中转,传输速率可能会大大降低.对此,除了假设更好的 socks5 代理服务器外,没有更好的方法。 4。4 扩展机制的缺点 XMPP 的扩展协议相当多,详细列表可以在 xmpp。org/extensions/ 找到。 但是通过扩展协议实现的功能,通常需要双方客户端均实现才能使用.有些还需要服务器做额外支持 (如 vcard—temp),而有名的 XMPP 服务器通常只会选择性实现扩展协议,所以要在现实中实现所需的 XMPP 扩展,就需要搭建全套的服务端、客户端方案,开发成本大.并且造成各方 XMPP 服务器实现不一致,出现功能不同的 XMPP “部落”,只能使用核心协议中已定义的部分进行通信。 [1] http://dia。org/zh—cn/XMPP [2] http://tools。ietf。org/html/rfc3920#page—9 [3] http://。org/html/rfc3920 [4] http://tools。ietf。org/html/rfc3921 [5] xmpp。org/extensions/ [6] books。google。com/books?id=SG3jayrd41cC&lpg=PP1&pg=PA165#v=onepage&q&f=false [7] 。org/html/rfc3921#page—26 [8] http://xmpp。org/extensions/xep—0071。html [9] xmpp。org/extensions/xep-0054。html [10] xmpp。org/extensions/xep-0047。html [11] /extensions/xep-0065。html [12] /extensions/xep-0096。html
发布者:admin,转转请注明出处:http://www.yc00.com/news/1689811766a288196.html
评论列表(0条)