XMPP节
核心XMPP工具集由三个基本节组成,分别为
、和 XMPP流由两份XML文档组成,通信的每个方向均有一个文档,这些文档有一个根元素,的子元素由可路由的节以及与流相关的顶级子元素构成。 <stream:stream> <iq type=’get’> <query xmlns=’jabber:iq:roster’ /> //请求自己的花名册 </iq> <presence/> //通知服务器她已在线并可以访问 <message to=’darcy@pemberley.lit’ from=’elizabaeth@longbourn.lit/ballroom’ type=’chat’> <body> I cannot talk of books in a ball-room; my head is always full of something else. </body> //发送消息 </message> <presence type=’unavailable’> // 声明自己不可访问并关闭 </stream:stream>
通用属性
from/to/type/id
from的属性并非由客户端提供,而是服务端进行的标记。
presence节
presence提供网络实体的可访问性。用户发出presence节,表明自己上线,这样可以会有更大的概率与别人通信(人们更愿意与在线的人交流),但是我们也不用担心任何人都可以看到自己的在线状态,除非我们订阅了该用户的状态,订阅之后,用户的状态信息会自动发送到订阅者处。
实际上,XMPP的presence节是一个简单的专用的发布-订阅方法。
在IM中,presence体现在花名册(roster)中,花名册保存有JID列表以及用户与这些JID的订阅关系,一旦上线,用户发送presence节,剩下的就由服务器处理了(通知自己在线,以及获取联系人的状态信息)
当有客户端的状态更新时都会给服务器发送presence消息,从而触发PresenceUpdateHandler中的process方法,此方法首先判断presence包中的type,分为以下几种方案:
- type为空
说明是第一次发送状态消息,
首先,服务器调用broadcastUpdate方法广播该消息给所有的好友。
然后,是初始化session的过程,initSession方法中首先检测该用户所有好友的在线状态,然后发送给该用户。
之后,从数据库中提取用户的离线消息,发送给用户。
最后,将type设置为available 。 - type为unavailable
说明用户下线,发送广播通知所有好友该用户下线。之后会把该session的状态设置为available,并调用SessionManager中的方法通知该id的其他resource此状态
message节
用于从一个实体向另外一个实体发送消息,并可以传输任何类型的结构化信息,不保证传输可靠性
message是一个非常基础的推模型,message通常用于IM,groupchat,警告和通知等。
message的type有如下几种:
- normal
类似于email,发出后不等待回应
- chat
用于两个实体间的实时通信
- groupchat
多用户聊天室中使用
- headline
用于发送警告或通知
- error
发送错误信息
结构如下:
<message from=madhatter@wonderland.lit/foo to=alice@wonderland.lit type="chat"> <body>Who are you?</body> <subject>Query</subject> </message>
除了type之外,典型的message节中还包含from、to或者id属性(用于目的追踪)。
to中的JID为消息的接受者,from是发送者的JID,但是from属性并非由客户端提供,而是发送者的服务端提供的,以避免地址模仿。
message节中也可以包含未在XMPP协议中定义的负载,可以用于扩展。
IQ节
Jane 向她的服务器发送了一个格式错误的花名册请求。服务器使用一个错误提示节作为响应 在重新发送正确的请求之后,服务器将Jane 的简短花名册响应给她。可以看到Elizabeth 和 Bingley 均在Jane 的联系人列表中。 Jane 试图将Darcy 添加到自己的花名册中,服务器用一个空白IQ-result 节来指出添加成功。 如果应答节只是成功确认,那么IQ-result 节通常是空白的。 在任何需要结果数据或者需要简单确认的场合中, 来源:节(它们定义了子元素) 不同,节通常只包含与它们功能相关的扩展元素。此外,每一对节必须匹配id 属性。
<iq from='jane@longbourn.lit/garden'
type='get'
id='roster1'>
<query xmlns='jabber:iq:roster'/>
</iq>
<iq to='jane@longbourn.lit/garden'
type='error'
id='roster1'>
<query xmlns='jabber:iq:roster'/>
<error type='cancel'>
<feature-not-implemented xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
<iq from='jane@longbourn.lit/garden'
type='get'
id='roster2'>
<query xmlns='jabber:iq:roster'/>
</iq>
<iq to='jane@longbourn.lit/garden'
type='result'
id='roster2'>
<query xmlns='jabber:iq:roster'>
<item jid='elizabeth@longbourn.lit' name='Elizabeth'/>
<item jid='bingley@netherfield.lit' name='Bingley'/>
</query>
</iq>
<iq from='jane@longbourn.lit/garden'
type='set'
id='roster3'>
<query xmlns='jabber:iq:roster'>
<item jid='darcy@pemberley.lit' name='Mr. Darcy'/>
</query>
</iq>
<iq to='jane@longbourn.lit/garden'
type='result'
id='roster3'/>
https://www.cnblogs.com/alighie/p/9540717.html