首页 > 代码库 > XMPP-可扩展的消息和出席信息协议(概述)

XMPP-可扩展的消息和出席信息协议(概述)

概述


  可扩展消息的和出席信息协议(XMPP)主要采用XML流实现在任意两个网络终端接近实时的交换结构化信息,XMPP提供一个通用的可扩展的框架来交换XML数据,用于准实时消息和出席信息以及请求-响应服务。

通用的架构


  XMPP没有指定任何特定的网络结构,但它通常是采用客户-服务器架构进行实现,其中客户端通过TCP方式使用XMPP访问服务器,服务器之间也采用TCP方式进行通信。

1.同一域名服务器和客户端组成的简单XMPP架构

  具有惟一名称的客户机通过相关的服务器与另外一个具有惟一名称的客户机进行通信,每个客户机执行客户机的协议表单,而服务器在表单中提供路由功能

2.包含网关的复杂XMPP架构

  针对不同域(XMPP域,短信服务(SMS)域和一个 SMTP 域)之间,网关可以把 XMPP 翻译成外部(非XMPP)消息系统,并把返回的消息翻译成 XMPP 。作为一个可扩展的协议,XMPP 对于在不同的端点协议间提供统一连接性来说是一个理想的中枢协议。XMPP 网关允许终止一个给定的客户端到服务器的会话,并且向目标端点协议发起一个新的会话(同时进行必要的协议转换)。

地址空间


概览  

  一个XMPP实体的地址被称为JID,一个合法的JID包含可选节点,域名,可选资源名,一个JID作为网络通讯ID,其具有唯一性

  XMPPJID *jid = [ node "@" ] domain [ "/" resource ];

  一个 JID 的每个合法部分(节点名,域名,资源名)的长度不能(MUST NOT)超过 1023 字节。也就是整体长度(包括 ‘@‘ 和 ‘/‘ )不能超过 3071 字节

[可选节点]域名[可选资源]

  域名:主要ID,一个域名标识引用的实体,并非总是一个服务器,它也可能是一个服务器的子域地址

  可选节点:第二ID,通常表示一个向服务器或网关请求和使用网络服务的实体(比如一个客户端),当然它也能够表示其他的实体(比如在多用户聊天系统中的一个房间)

    可选资源:通常表示一个特定的会话,连接(比如设备或者所在位置),或者一个附属于某个节点ID实体相关实体的对象(比如多用户聊天室中的一个参加者),也称第三ID

XML流和XML节 


概览

  XML流和XML节使得实体之间异步交换低负载的结构化信息成为可能

  XML流:

    一个XML流是一个容器,包含了两个实体之间通过网络交换的XML元素。一个XML流是由一个XML打开标签 <stream> (包含适当的属性和名字空间声明)开始的,流的结尾则是一个XML关闭L标签 </stream> 。在流的整个生命周期,初始化它的实体可以通过流发送大量的XML元素,用于流的握手(TLS握手或SASL握手)或XML节(此处主要指符合缺省名字空间的元素,包括<message/>,<presence/>, 或 <iq/> 元素)

    “初始的流”由初始化实体(通常是一个客户端或服务器)和接收实体(通常是一个服务器)握手,从接收实体来看,它就是那个初始实体的"会话".初始化流允许从初始化实体到接收实体的单向通信;为了使接收实体能够和初始实体交换信息,接收实体必须发起一个反向的握手(应答流).

  XML节:

    一个XML节是一个实体通过 XML 流向另一个实体发送的结构化信息中的一个离散的语义单位。任何XML节都是从一个XML流的下一级的某个打开标签(如 <presence>)开始,到相应的关闭标签(如 </presence>)(此处XML节仅限于<message/>, <presence/>, 和 <iq/> 元素)

  客户端与服务端进行会话:

    1.客户端发送一个打开标签<Stream>给服务器,初始化流(也可在此之前发送一段文本声明XML版本和支持的字符集)

    2.服务器回复一个XML流给客户端(也可在此之前发送一段文本声明)

    3.客户端完成SASL握手

    4.客户端发送关闭标签</stream>给服务器(或服务器发送给客户端)

    5.客户端与服务器彻底终结这个连接(通常为一个TCP连接)

通信类别

  使用 XMPP 的实时消息传递系统包含三大通信类别:

  • 消息传递,其中数据在有关各方之间传输;<message>
  • 联机状态,它允许用户广播其在线状态和可用性;<presence>
  • 信息/查询请求,它允许 XMPP 实体发起请求并从另一个实体接收响应。<iq>
 <stream>     <presence>        <show/>     </presence>     <message>        <body/>     </message>     <iq>        <query/>     </iq> </stream>

绑定到TCP

  虽然有很多非必需的连接使用XML流来绑定[TCP]连接(两个实体可以通过别的机制来互联,比如通过[HTTP]连接轮询),在客户和服务器通信的过程中,服务器必须允许客户端共享一个TCP连接来传输XML节,包括从客户端传到服务器和从服务器传到客户端。在服务器之间的通信过程中,服务器必须用一个 TCP连接 向对方发送 XML节,另一个 TCP连接(由对方初始化)接收对方的XML节,一共两个 TCP连接。

流的安全

  当XML流开始握手时,尽管可能存在某种共有的机制能够保证双向安全,但是“初始化流”(比如从初始化实体发给接收实体的流)和“应答流”(比如从接收实体发给初始化实体的流)还是必须安全的分开。在流被验证之间,实体不应该尝试通过流发送XML节;就算它这样做了,对方的实体也不能接受这些XML节,并且应该返回一个 <not-authorized/> 的流错误信息并且终止当前TCP连接上双方的XML流;注意,这仅仅是针对XML节(包含在缺省命名空间中的 <message/>, <presence/>, 和 <iq/> 元素),而不是指那些用于 TLS握手、SASL握手握手的流。

Stream属性

  • to            : 出现在初始化实体发给接受实体的XML流中,值为接受实体JID,若其出现在应答流中,初始化实体应忽略
  • from        : 出现在接收实体发给初始化实体的 XML 流的头当中,值为初始化实体JID,若其出现的初始化实体中,接受实体应忽略
  • id            : 用于接收实体发送给初始化实体 XML流的头中,由接受实体创建的唯一ID,也做初始化实体与接受实体之间的会话ID,若其出现在初始化流中,接受实体应忽略
  • xml:lang  : 包含在初始化发给接受实体的初始化流中,用于指定在流中传输的可读XML字符所使用的缺省语言,如该值没有则应用缺省值,如该值存在,则接受实体不能修改该值
  • version    : 版本支持

流错误

  流的根元素可以(MAY)包含一个 <error/> 子元素,由流的名字空间前缀作为它的前缀

<stream:error>     <defined-condition xmlns=‘urn:ietf:params:xml:ns:xmpp-streams‘/>    [optional text]     <text xmlns=‘urn:ietf:params:xml:ns:xmpp-streams‘ xml:lang=‘langcode‘>        descriptive text     </text></stream:error>

规则

以下规则适用于流级别的错误:
  • 它假定所有流级别的错误都是不可恢复的;所以,如果一个错误发生在流级别,发现这个错误的实体必须(MUST)发送一个流错误信息给另一个实体,发送一个关闭标签 </stream>,并终止这个流所在的TCP连接。
  • 如果这个错误发生在流刚开始设置的时候,接收实体必须(MUST)仍然发送一个开放标签 <stream> ,并在流元素中包含一个<error/>的子元素,然后发送一个关闭标签 </stream>,最后终止相应的TCP连接。在这种情况下,如果初始化实体在 ‘to‘ 属性中提供了一个未知的主机名,服务器应该(SHOULD)在终止之前,先在流的头信息的 ‘from‘ 属性中提供一个服务器认证的主机名.

流错误条件定义

以下流级别的错误条件是已定义的:
  • <bad-format/> -- 实体已经发送XML但是不能被处理;这个错误可以被更多特定的XML相关的错误替换,比如 <bad-namespace-prefix/>, <invalid-xml/>, <restricted-xml/>, <unsupported-encoding/>, 以及 <xml-not-well-formed/>,尽管更多特定的错误是首选的。 
  • <bad-namespace-prefix/> -- 实体发送的名字空间前缀不被支持,或者在一个需要某种前缀的元素中没有发送一个名字空间前缀.
  • <conflict/> -- 服务器正在关闭为这个实体激活的流,因为一个和已经存在的流有冲突的新的流已经被初始化。
  • <connection-timeout/> -- 实体已经很长时间没有通过这个流发生任何通信流量(可由一个本地服务策略来配置).
  • <host-gone/> -- 初始化实体在流的头信息中提供的‘to‘属性的值所指定的主机已经不再由这台服务器提供
  • <host-unknown/> -- 由初始化实体在流的头信息中提供的 ‘to‘ 属性的值和由服务器提供的主机名不一致.
  • <improper-addressing/> -- 一个在两台服务器之间传送的节缺少 ‘to‘ 或 ‘from‘ 属性(或者这个属性没有值).
  • <internal-server-error/> -- 服务器配置错误或者其他未定义的内部错误,使得服务器无法提供流服务.
  • <invalid-from/> -- 在‘from‘属性中提供的 JID 或 主机名地址,和认证的 JID不匹配 或服务器之间无法通过SASL(或回拨)协商出合法的域名,或客户端和服务器之间无法通过它进行认证和资源绑定。
  • <invalid-id/> -- 流 ID 或回拨 ID 是非法的或和以前提供的 ID 不一致.
  • <invalid-namespace/> -- 流名字空间和 "http://etherx.jabber.org/streams" 不相同或回拨名字空间和 "jabber:server:dialback" 不相同.
  • <invalid-xml/> -- 实体通过流发送了一个非法的XML给执行验证的服务器.
  • <not-authorized/> -- 实体试图在流被验证之前发送数据或不被许可执行一个和流协商有关的动作,接收实体在发送错误信息之前不允许处理厌恶的节。
  • <policy-violation/> -- 实体违反了某些本地服务策略;服务器可以选择在 <text/> 元素或应用程序定义的错误条件(元素)中详细说明策略。
  • <remote-connection-failed/> -- 服务器无法正确连接到用于验证或授权的远程实体。
  • <resource-constraint/> -- 服务器缺乏必要的系统资源为流服务。
  • <restricted-xml/> -- 实体试图发送受限的XML特性,比如一个注释,处理指示,DTD,实体参考,或保留的字符.
  • <see-other-host/> -- 服务器将不提供服务给初始化实体但是把它重定向到另一台主机;服务器应该在<see-other-host/>元素的XML字符数据中指明替代服务器名或IP地址(它必须(必须)是合法的域名标识)。
  • <system-shutdown/> -- 服务器正在关机并且所有激活的流正在被关闭。
  • <undefined-condition/> -- 错误条件不在本文已定义的错误条件列表之中;这个错误条件应该仅用于"应用程序定义条件"元素.
  • <unsupported-encoding/> -- 初始化实体以一个服务器不不支持的编码方式编码了一个流.
  • <unsupported-stanza-type/> -- 初始化实体发送了一个流的一级子元素但是服务器不支持.
  • <unsupported-version/> -- 由初始化实体在流的头信息中指定的‘version‘属性的值所指定的版本不被服务器支持;服务器可以在<text/>元素中指定一个它支持的版本号.
  • <xml-not-well-formed/> -- 初始化实体发送了一个不规范的XML(参考[XML])

参考资料:

http://www.ibm.com/developerworks/cn/xml/x-xmppintro/index.html

http://www.ibm.com/developerworks/cn/xml/tutorials/x-realtimeXMPPtut/index.html

 

XMPP-可扩展的消息和出席信息协议(概述)