以下示例展示一个服务器和对端服务器协商XML流,交换XML节, 和关闭已协商的流的数据流. 初始化服务器("Server1")是im.example.com; 接收服务器("Server2")是example.net 并且要求使用TLS; im.example.com递交一个证书并通过SASL EXTERNAL机制验证. 假定在发送初始化流头之前, Server1已经解析了一个SRV记录_xmpp-server._tcp.example.net并且已经打开了一个TCP连接到已解析的IP地址的声明的端口上. 注意Server1怎样声明内容命名空间"jabber:server"作为缺省的命名空间并为流相关的元素使用前缀, 反之Server2使用免前缀标准.
TLS
第一步: Server1初始化流到Server2:
S1: <stream:stream
from='im.example.com'
to='example.net'
version='1.0'
xmlns='jabber:server'
xmlns:stream='http://etherx.jabber.org/streams'>
第二步: Server2发送一个应答流头到Server1来应答:
S2: <stream
from='example.net'
id='hTiXkW+ih9k2SqdGkk/AZi0OJ/Q='
to='im.example.com'
version='1.0'
xmlns='http://etherx.jabber.org/streams'>
第三步: Server2发送流特性给Server1(在这个点上只有STARTTLS扩展, 它是强制协商的):
S2: <features xmlns='http://etherx.jabber.org/streams'>
<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'>
<required/>
</starttls>
</features>
第四步: Server1发送STARTTLS指令给Server2:
S1: <starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>
第五步: Server2通知Server1它被允许继续:
S2: <proceed xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>
第五步(替代): Server2通知Server1 STARTTLS协商失败了, 关闭流, 并中止TCP连接(于是, 流协商过程以不成功结束并且双方不再进行下一步):
S2: <failure xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>
</stream>
第六步: Server1和Server2尝试通过TCP完成TLS协商(详见TLS).
第七步: 如果TLS协商成功了, Server1在受TLS保护的TCP连接上初始化一个新流到Server2:
S1: <stream:stream
from='im.example.com'
to='example.net'
version='1.0'
xmlns='jabber:server'
xmlns:stream='http://etherx.jabber.org/streams'>
第七步(替代): 如果TLS协商不成功, Server2关闭TCP连接(所以, 流协商过程以不成功结束并且双方不再进行下一步).
SASL
第八步: Server2发送一个应答流头给Server1并带上可用的流特性(包括优先的SASL EXTERNAL机制):
S2: <stream
from='example.net'
id='RChdjlgj/TIBcbT9Keu31zDihH4='
to='im.example.com'
version='1.0'
xmlns='http://etherx.jabber.org/streams'>
S2: <features xmlns='http://etherx.jabber.org/streams'>
<mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
<mechanism>EXTERNAL</mechanism>
</mechanisms>
</features>
第九步: Server1选择EXTERNAL机制(包含一个"="的空应答):
S1: <auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl'
mechanism='EXTERNAL'>=</auth>
第十步: Server2返回成功:
S2: <success xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>
第十步(替代): Server2通知Server1验证失败了(所以, 流协商过程以不成功结束并且双方不再进行下一步):
S2: <failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
<not-authorized/>
</failure>
</stream>
第十一步: Server1初始化一个新流到Server2:
S1: <stream:stream
from='im.example.com'
to='example.net'
version='1.0'
xmlns='jabber:server'
xmlns:stream='http://etherx.jabber.org/streams'>
第十二步: Server2发送一个流头给并带上任何附加的特性(或, 在这个例子中, 一个空的特性元素)来应答:
S2: <stream
from='example.net'
id='MbbV2FeojySpUIP6J91qaa+TWHM='
to='im.example.com'
version='1.0'
xmlns='http://etherx.jabber.org/streams'>
S2: <features xmlns='http://etherx.jabber.org/streams'/>
节交换
现在Server1被允许通过已协商的从im.example.com到example.net的流发送XML节给Server2; 这里我们假定被传输的节就是前面演示的那些客户端-服务器通讯的节, 尽管是在一个服务器-服务器由'jabber:server'命名空间限定的流上.
Server1发送XML节给Server2:
S1: <message from='juliet@im.example.com/balcony'
id='ju2ba41c'
to='romeo@example.net'
type='chat'
xml:lang='en'>
<body>Art thou not Romeo, and a Montague?</body>
</message>
关闭
想不再发送更多消息, Server1关闭它到Server2的流但是等待从Server2的入站数据. (实践中, 流大部分时候保持打开一段时间, 因为Server1和Server2不是立刻知道流是否需要更多通讯.)
S1: </stream:stream>
和建议的流关闭握手一致, Server2同样关闭流:
S2: </stream>
Server1现在发送一个TLS close_notify警告, 从Server2接收一个close_notify警告应答, 然后中止当前的TCP连接.
转载:http://wiki.jabbercn.org/RFC6120