概述
XMPP是一个开放式的XML协议,设计用于准实时消息和出席信息以及请求-响应服务。
通用的架构
通常采用客户端服务器架构进行实现,其中客户端通过TCP方式使用XMPP访问服务器,服务器之间也采用TCP方式进行通信。
XMPP架构.png
服务器
充当xmpp通信的一个智能抽象层,负责
- 对受验证的客户端,服务器以及其他实体之间以xml流的形式的连接和会话进行管理。
- 在这些实体间使用xml流对合理编址的xml节进行路由
- 存储和处理客户端使用的数据
客户端
通过TCP连接直接连接到服务器,并通过xmpp获得由服务器以及联合服务器所提供的全部功能。多个不同的客户端可以同时登陆并且并发的连接到一个服务器,每个不同资源的客户端通过xmpp地址的资源标识符来区分。建议的客户端和服务器连接的端口时5222
网关
网关是一个特殊用途的服务器端的服务,主要功能是把xmpp翻译成外部消息系统,并把返回的消息翻译成xmpp.
网络
每个服务器都是由一个网络地址来标识的并且服务器之间的通信是客户-服务器协议的直接拓展。任意两个服务器之间的通信是可选的,如果被激活,那么这种通信应该通过XML流绑定到TCP连接上进行。建议的服务器和服务器连接的端口时5269
注
xmpp系统涉及更多的域间连接,当你给不在同一个域中的联系人发送xmpp消息时,你的客户端连接到你的“家用”服务器,然后直接连接到你的联系人的服务器,而没有中间跳过。
地址空间
概述
因为xmpp通讯实在网络上,所以每个xmpp实体都需要一个地址,称为JabberID(JID)。一个合法的JID包括一组排列好的元素,包括域名(domain identifier), 节点名(node identifier), 和资源名(resource identifier)。<user@host/resource>这种结构,最常用来标识一个即时消息用户,这个用户所连接的服务器,以及这个用户用于连接对资源。一个JID的每一个合法部分的长度不能超过1023字节,也就是整体长度(包括@和/)不能超过3071.
注
节点类型不一定是客户端,比如:聊天室中 room@service这里的room是聊天室的名字,service是多用户聊天服务的主机名,而加入了这个聊天室的某个特定的用户多地址则是<room@service/nick>
域名
域名是一个主要的ID,并且是JID中唯一必须的元素。(一个纯粹的域名也是一个合法的JID)。它通常代表网络的网关或者“主”服务器,其他实体通过连接它来实现xml转发和数据管理功能。然而,由一个域名标识引用的实体,并非总是一个服务器,也可能是一个服务器子域名地址。
节点名
是一个可选的第二ID,放在域名之前并用符号“@”分开。它通常表示一个向服务器或网关请求和使用网络服务的实体(比如一个客户端),当然也可能表示其他实体(如聊天室中的一个房间)。
33资源名
是一个可选的第三ID,它放在域名后面并由“/”分开,资源名可以跟在node@domain后面也可以跟在<domain>后面。它通常表示一个特定的会话连接,或者附属于某个节点ID实体相关实体的对象。
XML流
XMPP本质上是一种XML流技术。
客户端开始和XMPP服务器会话,会打开一个长时间的TCP连接,然后和服务器协商一个流。一旦你和你的服务器建立了一个XML流,你和你的服务器可以通过流交换三个特殊的XML片段:<message/>,<presence/>,<iq/>.这些片段称为XML节。是XML中最有意义的基本单元,而且一旦你已建立一个XML流,你可以通过流发送无数个节。
举例:
C: <stream:stream>
C: <presence/>
C: <iq type="get">
<query xmlns="jabber:iq:roster"/>
</iq>
S: <iq type="result">
<query xmlns="jabber:iq:roster">
<item jid="suke@skh.whu.edu.cn"xs/>
<item jid="gmz@skh.whu.edu.cn"/>
<item jid="beta@skh.whu.edu.cn"/>
</query>
</iq>
C: <message from="suke@skh.whu.edu.cn"
to="beta@skh.whu.edu.cn">
<body>Off with his head!</body>
</message>
S: <message from="lj@skh.whu.edu.cn"
to="cyl@skh.whu.edu.cn ">
<body>You are all pardoned.</body>
</message>
C: <presence type="unavailable"/>
C: </stream:stream>
绑定到TCP
客户端与服务器通信的过程中,服务器必须允许客户端共享一个TCP连接来传输XML节,包括从客户端传到服务器和从服务器传到客户端。
服务器到服务器的通信过程中,服务器必须用一个TCP连接向对方发送XML节,另一个TCP连接(由对方初始化)接受对方的XML节,一共两个TCP连接。
通讯原语
在XMPP中,一个节可以被认为是通讯的基本单位,类似于一个数据包或其他网络协议的消息。
有几个因素决定了一个节的意义
节元素的名称,有message,presence或者iq。每一种节服务器对它们的路由方式不同,并且客户端对它们的处理也不同
Type属性的值依赖于实际中节种类而变化。这个值由收件人来进一步区分每个节是如何处理的。
子元素,定义了节的有效载荷,有效载荷可能呈现给用户或者按照规范定义的有效载荷的命名空间以自动的方式处理。
消息
<message/>节是使用基本的“push”方法从一个地方到另一个地方得到消息,消息是不可告知的,它是一种“fire-and-forget”的机制从一个地方到另一个地方快速获取信息。
消息的type
normal:单个的消息,对应的回应可能会或者可能不会很快到来。
chat:在两个实体间店实时对话中交换
groupchat:多用户聊天室中交换
headline:发送警告和通告,并不期望有回应
error:对先前发送消息发生错误,实体检测这个问题将返回一个类型error的消息。
消息的to:预期收件人的JabberID
消息的from:发送者的JabberID,from地址不由发送客户端提供,而是由发送者的服务器添加邮戳,以避免地址欺骗。
消息也包含有载荷元素。核心XMPP规格定义了一些非常基本的有效载荷,例如<body/>和<subject/>,被用于人对人的聊天信息,消息(和其他类的节)可以包含在核心XMPP规格中没有定义的有效载荷
<message from="suke@skh.whu.edu.cn"
to="beta@skh.whu.edu.cn"
type="chat">
<body>Who are you?</body>
<subject>Query</subject>
</message>
出席
出席通知其他实体的网络可用性,并且使你能够知道其他实体是否在线和可用于通讯。
它是一个在互联网上沟通和合作的催化剂,因为人们更容易与你交流,如果他们知道你是否在线。
只有通过你授权的人才能看到你是否在线。这个授权被称为出席订阅(presence subscription)
订阅模型意味着XMPP的<presence/>节本质上是一个简单、专门的发布-订阅方法,通过这种形式,当你在线,然后将状态改为“会议中”或者“午餐中”,然后离线,向你订阅了出席的人将收到更新的出席信息。
<presence from="suke@skh.whu.edu.cn">
<show>xa</show>
<status>down the rabbit hole!</status>
</presence>
在XMPP的IM应用中,出席通常显示在你的允许出席的一种联系人列表的名册中(roster)。你的名册包含JabberIDs列表和你的出席订阅状态。当你在线时,你向你的服务器宣告你的出席,然后服务器将你在线通知告诉你的联系人,并且获得他们的当前出席显示在你的客户端界面上。
信息/查询
信息/查询(IQ)节提供了一种用于请求-应答交互和简单工作流的结构.
和<message/>节不同,一个IQ节能包含仅有一个有效载荷,用于定义处理的请求或接收人采用的行为。
发送IQ节的实体必须总是接收一个回复(通常由目的接收者或接受者的服务器产生)。
请求和应答通过使用id属性跟踪,id属性由请求实体生成,并被包含在应答的实体中
信息/查询type
get
请求实体信息,例如请求注册一个账户(类似于HTTP GET)。
set
请求实体提供一些信息或作出一个请求(类似于HTTP POST或PUT)。
result
应答实体返回get操作的结果(例如一个实体必须提供信息用来注册账户),或者确认一个set请求(类似于一个HTTP200状态码)。
error
应答实体或一个中间实体,例如XMPP服务器,通知请求实体它不能处理get或set请求(例如,因为请求的格式不正确,请求实体无权执行该操作等)。早期在HTTP中使用的数字错误代码已被可扩展错误条件的XML元素取代。
IQ或message?
XMPP消息节提供“fire-and-forget”传输方式,该方式最适合用于人类可读文本、警告、通知,并且任何时候你都不需要去确保内容是否真的被传递出去。IQ节提供一种更可靠的传输,优化了结构化数据的交换,通常是非人类可读数据.
举例
苏克通过发送一个IQ-get,该请求包含一个由jabber:iq:roster命名空间限定的空有效载荷,苏克通过发送一个IQ-get,该请求包含一个由jabber:iq:roster命名空间限定的空有效载荷
<iq from="suke@skh.whu.edu.cn"
id="rr82a1z7"
to="skh.whu.edu.cn"
type="get">
<query xmlns="jabber:iq:roster"/>
</iq>
服务器回复该命名空间限定一个非空的有效载荷,在这种情况下,包含一个<item/>元素对应名册中的一个联系人。
<iq from="skh.whu.edu.cn"
id="rr82a1z7"
to="suke@skh.whu.edu.cn"
type="result">
<query xmlns="jabber:iq:roster">
<item jid="suke@skh.whu.edu.cn"/>
<item jid="gmz@skh.whu.edu.cn"/>
<item jid="beta@skh.whu.edu.cn"/>
</query>
</iq>
苏克使用IQ-set向名册中添加一个新的联系人:
<iq from="suke@skh.whu.edu.cn"
id="ru761vd7"
to="skh.whu.edu.cn"
type="set">
<query xmlns="jabber:iq:roster">
<item jid="gmz@skh.whu.edu.cn"/>
</query>
</iq>
苏克也可以使用IQ-set向名册中添加一个新的联系人:
<iq from=" skh.whu.edu.cn "
id="ru761vd7"
to=" suke@skh.whu.edu.cn /Psi"
type="result"/>
</iq>
IQ-get或IQ-set的有效载荷总是通过由一个特定的XML命名空间限定的自有格式,这些命名空间由许多XMPP协议文档之一来指定。你可以想象每个有效载荷作为一个命令由接收人处理。IQ-get请求一种特定的信息,例如注册表、配置数据、服务发现信息或联系人列表。IQ-set创建、更新或删除一种特定的信息,例如已完成的表单、已更新的配置数据或者向联系人列表添加。
参考资料:
xmpp-权威指南
xmpp-RFC3920
交流群
移动开发交流群:264706196
网友评论