1

xmpp简介

XMPP(Extensible Messageing and Presence Protocol:可扩展消息与存在协议)RFC3920

XMPP的基本网络结构

XMPP没有指定任何特定的网络结构,但它通常是采用客户-服务器 架构进行实现,其中客户端通过TCP方式使用XMPP访问服务器,服务器之间也采用TCP方式进行通信。
以下是这一架构的抽象的示意图 (这里 "-" 表示使用 XMPP 通讯, "=" 表示可使用任何协议通讯)。

clipboard.png

符号的含义如下:
C1, C2, C3 = XMPP 客户端
S1, S2 = XMPP 服务器
G1 = 一个XMPP和外部(非XMPP)消息网络之间进行“翻译”的网关
FN1 = 一个外部消息网络
FC1 = 外部消息网络上的一个客户端

  • 服务器 对受验证的客户端,服务器以及其他实体之间以XML流形式的连接和会话进行管理。
  • 客户端 大部分客户端通过 TCP 连接直接连到服务器,并通过XMPP获得由服务器以及联合服务器所提供的全部功能
  • 网关 把 XMPP 翻译成外部(非XMPP)消息系统,并把返回的消息翻译成 XMPP

JID格式

jid = [ node "@" ] domain [ "/" resource ]
domain = fqdn / address-literal
fqdn = (sub-domain 1*("." sub-domain))
sub-domain = (internationalized domain label)
address-literal = IPv4address / IPv6address

e.g.:
username@mwee.cn/diancan

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

steam格式

<?xml version='1.0'?>
<stream:stream to='example.com' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' version='1.0'>
      
      ....
      
</stream:stream>

<?xml version='1.0'?>
<stream:stream from='example.com' id='someid' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' version='1.0'>

    ....
          
</stream:stream>

一个XML流相当于一个会话期间所有XML节的一个信封。我们可以简单的把它描述成下图:

clipboard.png

clipboard.png

xml节格式

通用属性
以下五种属性通用于 message, presence, 和 IQ 节:

  • to 预期接收者的JID
  • from 表示发送者的 JID
  • id 可选属性,用于为节的内部跟踪发送实体
  • type 指明消息、出席信息或IQ节的意图或上下文的详细信息 (如get set等)
  • xml:lang 可选 生命字符集

message 消息

<message/>节类型可以被看作是一个"push"机制用于一个实体推送信息给另一个实体,类似发生在email系统中的通信. 所有消息节应该处理一个表明预定的消息接收者的'to'属性;接收了这样一个节之后,一个服务器应该路由或递送它给预定的接收者.

presence出席

<presence/> 元素可以被看作一个基本的广播或“出版-订阅”机制,用于多个实体接收某个已订阅的实体的信息(在这里,是网络可用性信息). 通常,一个发行实体应该不带'to'属性发送一个出席信息,这时这个实体所连接的服务器应该广播或复用那个节给所有订阅的实体.无论如何,一个发行实体也可以带'to'属性发送一个出席信息节,这时服务器应该路由或递送这个节给预定的接收者.

iq info/query

信息/查询(Info/Query),或曰IQ,是一个 请求-回应 机制,某些情况下类似[HTTP].IQ语义学使一个实体能够向另一个实体做出请求并做出应答. 请求和应答所包含的数据定义在IQ元素的一个直接的子元素的名字空间声明中, 并且由请求实体用'id'属性来跟踪这一交互行为. 因而,IQ交互伴随着一个结构化的数据交换的通用模式例如 get/result 或 set/result (尽管有时候会以一个错误信息应答某个请求):

clipboard.png

流示例

"C"表示从客户端发给服务器,"S"表示从服务器发给客户端

一个基本的 "会话":

   C: <?xml version='1.0'?>
      <stream:stream to='example.com' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' version='1.0'>
 
   S: <?xml version='1.0'?>
      <stream:stream from='example.com' id='someid' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' version='1.0'>
   ...  encryption, authentication, and resource binding ...
 
   C:   <message from='juliet@example.com' to='romeo@example.net' xml:lang='en'>
           <body>Art thou not Romeo, and a Montague?</body>
        </message>
 
   S:   <message from='romeo@example.net' to='juliet@example.com' xml:lang='en'>
          <body>Neither, fair saint, if either thee dislike.</body>
        </message>
 
   C: </stream:stream>
 
   S: </stream:stream>

客户端-服务器
以下例子展示一个客户端使用STARTTLS保护数据流

1: 客户端初始化流给服务器:
   <stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' to='example.com' version='1.0'>

2: 服务器发送一个流标签给客户端作为应答:
   <stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' id='c2s_123' from='example.com' version='1.0'>

3: 服务器发送 STARTTLS 范围给客户端(包括验证机制和任何其他流特性):
   <stream:features>
     <starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'>
       <required/>
     </starttls>
     <mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
       <mechanism>DIGEST-MD5</mechanism>
       <mechanism>PLAIN</mechanism>
     </mechanisms>
   </stream:features>

4: 客户端发送 STARTTLS 命令给服务器:
   <starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>

5: 服务器通知客户端可以继续进行:
   <proceed xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>
  (或者): 服务器通知客户端 TLS 握手失败并关闭流和TCP连接:
   <failure xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>
   </stream:stream>

6: 客户端和服务器尝试通过已有的TCP连接完成 TLS 握手.
7: 如果 TLS 握手成功, 客户端初始化一个新的流给服务器:
   <stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' to='example.com' version='1.0'>
  (或者): 如果 TLS 握手不成功, 服务器关闭 TCP 连接.

8: 服务器发送一个流头信息应答客户端,其中包括任何可用的流特性:
   <stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' from='example.com' id='c2s_234' version='1.0'>
   <stream:features>
     <mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
       <mechanism>DIGEST-MD5</mechanism>
       <mechanism>PLAIN</mechanism>
       <mechanism>EXTERNAL</mechanism>
     </mechanisms>
   </stream:features>

9: 客户端继续 SASL 握手

xmpp限制

Demo

...

参考

文章参考-XMPP协议实现原理介绍
实现可扩展消息传递和到场协议(XMPP)
RFC3920


vlean
113 声望4 粉丝

开启新一轮的自我成长


引用和评论

0 条评论