Jabberd/XMPP 学习之八:客户端-服务器示例

前端之家收集整理的这篇文章主要介绍了Jabberd/XMPP 学习之八:客户端-服务器示例前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

以下例子展示客户端和服务器协商XML流,交换XML节,和关闭已协商的流的XMPP数据流. 服务器是"im.example.com",该服务器要求使用TLS,客户端验证使用SASL SCRAM-SHA-1机制,客户端帐号是<juliet@im.example.com>而密码是"r0m30myr0m30",并且客户端在这个流上提交了一个资源绑定请求. 我们假设在发送初始化流头之前,客户端已经解析了_xmpp‑client._tcp.im.example.com的SRV记录并已经打开一个TCP连接到已解析的IP地址和声明的端口上.

TLS

第一步: 客户端初始化流到服务器:

@H_301_18@C: <stream:stream
     from='juliet@im.example.com'
     to='im.example.com'
     version='1.0'
     xml:lang='en'
     xmlns='jabber:client'
     xmlns:stream='http://etherx.jabber.org/streams'>

第二步: 服务器发送一个应答流头给客户端来应答:

@H_301_18@S: <stream:stream id='t7AMCin9zjMNwQKDnplntZPIDEI=' 'http://etherx.jabber.org/streams'>

第三步: 服务器发送流特性给客户端(在这个点上只有STARTTLS扩展,它是强制协商的):

@H_301_18@S: <stream:features> <starttls 'urn:ietf:params:xml:ns:xmpp-tls'> <required/> </starttls> </stream:features>

第四步: 客户端发送STARTTLS命令给服务器:

@H_301_18@C: <starttls 'urn:ietf:params:xml:ns:xmpp-tls'/>

第五步: 服务器通知客户端允许继续:

@H_301_18@S: <proceed 'urn:ietf:params:xml:ns:xmpp-tls'/>

第五步(替代): 服务器通知客户端STARTTLS协商失败,关闭XML流,并中止TCP连接(所以,流协商处理以不成功而结束并且双方不再进入下一步):

@H_301_18@S: <failure 'urn:ietf:params:xml:ns:xmpp-tls'/> </stream:stream>

第六步: 客户端和服务器尝试通过现有的TCP连接完成TLS协商(详见TLS).

第七步: 如果TLS协商成功,客户端通过TLS保护的TCP连接初始化一个新的流到服务器:

'http://etherx.jabber.org/streams'>

第七步(替代): 如果TLS协商不成功,服务器关闭TCP连接(所以,流协商处理以不成功而结束并且双方不再进入下一步):

SASL

第八步: 服务器发送流头给客户端并带上任何可用的流特性来应答:

'vgKi/bkYME8OAj4rlXMkpucAqe4=' 'http://etherx.jabber.org/streams'>@H_301_18@ S: <stream:features> <mechanisms 'urn:ietf:params:xml:ns:xmpp-sasl'> <mechanism>@H_301_18@SCRAM-SHA-1-PLUS</mechanism> <mechanism>@H_301_18@SCRAM-SHA-1</mechanism> <mechanism>@H_301_18@PLAIN</mechanism> </mechanisms> </stream:features>

第九步: 客户端选择一个验证机制(在这个场景中,是 SCRAM-SHA-1),包含初始化应答数据:

@H_301_18@C: <auth "urn:ietf:params:xml:ns:xmpp-sasl" mechanism="SCRAM-SHA-1">@H_301_18@ biwsbj1qdWxpZXQscj1vTXNUQUF3QUFBQU1BQUFBTlAwVEFBQUFBQUJQVTBBQQ== </auth>

解码之后的 base 64 数据是 "n,n=juliet,r=oMsTAAwAAAAMAAAANP0TAAAAAABPU0AA".

第十步: 服务器发送挑战:

@H_301_18@S: <challenge "urn:ietf:params:xml:ns:xmpp-sasl">@H_301_18@ cj1vTXNUQUF3QUFBQU1BQUFBTlAwVEFBQUFBQUJQVTBBQWUxMjQ2OTViLTY5Y TktNGRlNi05YzMwLWI1MWIzODA4YzU5ZSxzPU5qaGtZVE0wTURndE5HWTBaaT AwTmpkbUxUa3hNbVV0TkRsbU5UTm1ORE5rTURNeixpPTQwOTY= </challenge>

解码后的 base 64 数据是 "r=oMsTAAwAAAAMAAAANP0TAAAAAABPU0AAe124695b-69a9-4de6-9c30-b51b3808c59e,s=NjhkYTM0MDgtNGY0Zi00NjdmLTkxMmUtNDlmNTNmNDNkMDMz,i=4096" (实际数据中是没有换行的).

第十一步: 客户端发送一个应答:

@H_301_18@C: <response "urn:ietf:params:xml:ns:xmpp-sasl">@H_301_18@ Yz1iaXdzLHI9b01zVEFBd0FBQUFNQUFBQU5QMFRBQUFBQUFCUFUwQUFlMTI0N jk1Yi02OWE5LTRkZTYtOWMzMC1iNTFiMzgwOGM1OWUscD1VQTU3dE0vU3ZwQV RCa0gyRlhzMFdEWHZKWXc9 </response>

解码后的 base 64 数据是 "c=biws,r=oMsTAAwAAAAMAAAANP0TAAAAAABPU0 AAe124695b-69a9-4de6-9c30-b51b3808c59e,p=UA57tM/ SvpATBkH2FXs0WDXvJYw=" (实际数据中是没有换行的).

第十二步: 服务器通知客户端成功了,并且包含了额外的数据:

@H_301_18@S: <success 'urn:ietf:params:xml:ns:xmpp-sasl'>@H_301_18@ dj1wTk5ERlZFUXh1WHhDb1NFaVc4R0VaKzFSU289 </success>

解码后的 base 64 数据是 "v=pNNDFVEQxuXxCoSEiW8GEZ+1RSo=".

第十二步(替代): 服务器返回一个SASL错误给客户端(所以,流协商处理以不成功结束并且双方不再进行下一步):

'urn:ietf:params:xml:ns:xmpp-sasl'> <not-authorized/> </failure> </stream>

第十三步: 客户端初始化一个新的流到服务器:

'http://etherx.jabber.org/streams'>

资源绑定

第十四步: 服务器发送一个流头到客户端并带上支持的特性(在这个场景中,是资源绑定)来应答:

'gPybzaOzBmaADgxKXu9UClbprp0=' 'http://etherx.jabber.org/streams'>@H_301_18@ S: <stream:features> <bind 'urn:ietf:params:xml:ns:xmpp-bind'/> </stream:features>

在被通知资源绑定是强制协商之后,客户端需要绑定一个资源到流; 这里我们假定客户端提交了一个自然人可读的文本字符串.

第十五步: 客户端绑定一个资源:

@H_301_18@C: <iq 'yhc13a95' type='set'> <bind 'urn:ietf:params:xml:ns:xmpp-bind'> <resource>@H_301_18@balcony</resource> </bind> </iq>

第十六步: 服务器接受提交的资源部分并通知客户端资源绑定成功:

@H_301_18@S: <iq 'result'> <bind 'urn:ietf:params:xml:ns:xmpp-bind'> <jid>@H_301_18@ juliet@im.example.com/balcony </jid> </bind> </iq>

第十六步(替代): 服务器返回错误给客户端(所以,流协商处理以不成功结束并且双方不再进入下一步):

'error'> <error 'cancel'> <conflict 'urn:ietf:params:xml:ns:xmpp-stanzas'/> </error> </iq>

节交换

现在客户端被允许通过协商好的流发送XML节了.

@H_301_18@C: <message 'juliet@im.example.com/balcony' 'ju2ba41c' 'romeo@example.net' 'chat' 'en'> <body>@H_301_18@Art thou not Romeo,and a Montague?</body> </message>

如果必要,发送者的服务器和预定的接收者的服务器协商XML流(见@L_301_1@).

预定的接收者应答,并且消息被递送到客户端.

@H_301_18@E: <message 'romeo@example.net/orchard' 'en'> <body>@H_301_18@Neither,fair saint,if either thee dislike.</body> </message>

客户端随后可以通过这个流继续发送和接收不限数量的XML节.

关闭

不想发送更多的消息,客户端关闭它到服务器的流,不在等待来自服务器的入站数据了.

@H_301_18@C: </stream:stream>

4.4一致,服务器可能发送额外的数据给客户端然后才关闭到该客户端的流.

@H_301_18@S: </stream:stream>

客户端现在发送一个 TLS close_notify 警告,从服务器接收到一个 close_notify 警告应答,然后中止当前的TCP连接.


转自:http://wiki.jabbercn.org/RFC6120

猜你在找的XML相关文章