XMPP(eXtensible Messaging and Presence Protocol,可扩展消息处理和现场协议)是一种在两个地点间传递小型结构化数据的协议。在此基础上,XMPP协议已经被用来构建大规模即时通讯系统、游戏平台、协做空间及语音和视频会议系统。编程
XMPP由几个小的构造块组成,并在此基础上扩展出了更多的构造块。XMPP中有众多系统:发布-订阅服务、多人聊天、表单检索与处理、服务发现、实时数据传输、隐私处理及远程过程调用等。安全
大多数社交媒体(Facebook及Twitter)也采用了XMPP协议。服务器
与其余协议同样,XMPP定义了在两个或者更多通讯实体间传递数据所采用的格式。对于XMPP,实体一般是指客户端服务器,可是其也容许客户端与客户端或服务器端与服务器端的通讯。网络
在XMPP上交换的是XML数据,采用这种格式,使XMPP协议得到了极大的可扩展性,由于使用XML能够方便的新增功能并保证先后向兼容。使用XML较二进制协议占用更大的带宽,但得到的优点是具备了几乎无限的可扩展性。session
用户能够向XMPP Standards Foundation注册协议扩展。负载均衡
在XMPP中,XML数据被组织为了一对流,每一个流分别对应通讯的一个方向。每一个XML流均由一个开始元素、后跟XMPP节和其余顶级元素,而后是一个结束元素组成。每一个XMPP节(可带有子元素及属性)均是该流的一级子元素。在XMPP链接末尾,这两个流造成了一对有效的XMPP文档。编程语言
XMPP节构成了该协议的核心部分,而XMPP应用程序则关注如何发送和响应各类类型的节。节可能包含网络上其余实体的信息、相似于电子邮件的我的消息或为计算机处理而设计的结构化数据。ide
<message to=’elizabeth@longbourn.lit’ from=’darcy@pemberley.lit/dance’ type=’chat’> <body>what think you of books</body> </message>
在一个典型的XMPP会话中,一个上述的节将会从darcy的XMPP客户端发送到她的XMPP服务器,她的服务器将会注意到该节的目的地是某个远程服务器上的一个实体,所以与该远程服务器先创建XMPP链接,并将消息转发该处。工具
这种通讯网络与电子邮件相似,但与电子邮件服务器不一样的是,XMPP间的服务器能够直接通讯,而不须要借助中间服务器。加密
这种直接通讯避免了垃圾信息的干扰,且还支持经过TLS(Transport Layer Security,传输层安全)来加密通讯并经过SASL(Simple Authentication and Security Layers,简单身份验证与安全层)实现身份验证机制。
XMPP使用传递短小信息来设计的,而非针对大型数据块,但XMPP可以用来协商并创建可在端点间传递大型数据块的带内或者带外传输。
最初各大公司发布的ICQ均基于其公司运营的专有协议和网络(ICQ,Yahoo Pager)。
开发人员企图互通这些IM的努力因为协议的闭源特性失败了。
1991年1月Jeremie Miller发布了Jabber项目,Jabber是基于XML的去中心化的即时通讯协议,同时也是一个叫jabberd的服务器实现。
2000年5月,Jabber的核心协议稳定,jabberd也正式发布了。
2001年,JSF(Jabber Software Foundation,Jabber软件基金会)成立,并开始围绕jabber协议作规范性工做。
2002年12月,JSF向IETF提交了核心规范,并成立了一个IETF小组。
2004年10月,这个标准化进程产生了Jabber协议的改进版,更名为XMPP,其文档成为RFC标准,编号分别为3920、392一、3922和3923。
最初开发人员向JSF提交的扩展称为JEP(Jabber Extension Proposal,Jabber扩展提议)。最终随着Jabber过分到XMPP,JSF改名为XSF(XMPP Standard Foundation,XMPP标准基金会)和XEP(XMPP Extension Proposal,XMPP扩展提议)。
2005年XMPP技术开始大规模部署,例如Google Talk。
先进有大约300个XEP,并有数十种客户端和服务端实现,开源及商用均有,实际上,任何编程语言均可以找到这样一个库来加速XMPP开发进程。
任何XMPP网络都是由若干角色组成,能够分为服务器端、客户端、组件和服务器插件。
XMPP网络与WWW网络及EMAIL网络不一样,XMPP服务器之间寻址只会跳一次,而EMAIL协议则会有多个中转服务器,XMPP保存完整的列表。
XMPP服务器是任何XMPP网络的通讯系统,服务器的任务就是为XMPP节提供路由。不管这些节是从内部的一个用户发往另一个用户仍是本地用户发送给服务器。
一组可以相互通讯的XMPP服务器构成了XMPP网络。
XMPP服务器老是容许用户链接到本身,可是也能够编写直接使用服务器-服务器协议的应用和程序,来减轻路由消耗。
Ejabberd、Openfire和Tigase是三种可以运行在Windows,Mac OS X和Linux的开源服务器。
M-Link和Jabber XCP是商用产品。
大多数XMPP实体均是客户端,经过客户端-服务器协议链接到XMPP服务器。
客户端必须向某个地方的XMPP服务器进行身份验证。服务器会将该客户端发送的全部节路由到合适的目的地。
服务器还负责管理客户端会话的其余几个方面,包括花名册及裸地址。
不只仅是客户端可以链接到XMPP服务器,大多数服务器还支持外部服务器组件。这些组件经过添加某种新服务来加强服务器的行为。这些组件在服务器内有各自的身份和地址,但运行在外部并经过组件协议通讯。
组件协议(XEP-0114)可让开发人员以一种服务器不可知的方式建立服务器扩展,例如多人聊天服务。
组件也须要向XMPP服务器进行身份验证,但要较客户端的彻底SASL验证简单,例如口令。
每一个组件编程服务器内部一个可单独寻址的实体,在外界看相似于一个子服务器。除了基本节以外,XMPP服务器不会代替已链接组件来管理其余节的路由。
服务器还容许组件在内部自行路由或管理节,于是更为灵活。
许多XMPP服务器还支持使用插件进行扩展,但插件深刻到服务器内部,有较高的效率以及最低的通用性。
插件通常是绑定特定类型的服务器的。
XMPP网络上的每一个实体都有一个或多个地址(称为JID,jabber identifier)。一般相似于:
darcy@pemberley.lit和elizabeth@longbourn.lit就是两个JID。
JID由三个部分组成,节点、域和资源,域是必须的,其余两个部分是可选的。
域是实体(服务器、组件或插件)可解析的DNS名称。仅由域组成的JID是有效地址,表示服务器地址。指向域的节将由服务器自身处理,并可能被路由到某个组件或插件。
本地部分一般用来识别域中的一个特定用户,位于@前。本地部分也能够用来识别其余对象,如某个聊天室。
JID的资源部分一般会标识一个特定客户端的XMPP链接。对于XMPP客户端而言,每一个链接均被指派一个资源。如darcy@perberley.lit想要链接他的书法和图书馆则能够经过
darcy@perberley.lit/study和darcy@perberley.lit/library来寻址,这样避免了用户在打开多个连接时消息没法找到正确的处理器。主要注意的是,资源部分是区分大小写的。
JID划分为两种类型:
完整JID去除资源部分的地址,客户端的裸JID有些特殊,这是由于服务器本身将处理发往客户端的裸JID节。裸JID能够视为寻址用户的帐户,而不是客户端。
最为具体的地址
核心XMPP工具集由三个基本节组成,分别为<presence>、<message>和<iq>
XMPP流由两份XML文档组成,通讯的每一个方向均有一个文档,这些文档有一个根元素<stream:stream>,<stream:stream>的子元素由可路由的节以及与流相关的顶级子元素构成。
<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节,代表本身上线,这样能够会有更大的几率与别人通讯(人们更愿意与在线的人交流),可是咱们也不用担忧任何人均可以看到本身的在线状态,除非咱们订阅了该用户的状态,订阅以后,用户的状态信息会自动发送到订阅者处。
实际上,XMPP的presence节是一个简单的专用的发布-订阅方法。
在IM中,presence体如今花名册(roster)中,花名册保存有JID列表以及用户与这些JID的订阅关系,一旦上线,用户发送presence节,剩下的就由服务器处理了(通知本身在线,以及获取联系人的状态信息)
用于从一个实体向另一个实体发送消息,并能够传输任何类型的结构化信息,不保证传输可靠性
message是一个很是基础的推模型,message一般用于IM,groupchat,警告和通知等。
message的type有以下几种:
相似于email,发出后不等待回应
用于两个实体间的实时通讯
多用户聊天室中使用
用于发送警告或通知
发送错误信息
<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协议中定义的负载,能够用于扩展。
表示Info/Query,为XMPP通讯提供请求及响应机制,相似于GET/POST/PUT方法。
IQ只能包含一个payload,而且定义了须要由服务器处理的请求或者动做。相对于message来讲,IQ具备更好的可靠性,因其要求收到回应。
IQ中包含有id属性,用于识别服务器发回的响应。
用于请求信息,相似于HTTP Get
提供信息或请求,相似于HTTP POST/PUT
响应请求,相似于HTTP 200
错误信息
<iq from=alice@wonderland.lit/pda id="rr82a1z7" to=alice@wonderland.lit type="get"> <query xmlns="jabber:iq:roster"/> </iq>
<iq from=alice@wonderland.lit id="rr82a1z7" to=alice@wonderland.lit/pda type="result"> <query xmlns="jabber:iq:roster"> <item jid="whiterabbit@wonderland.lit"/> <item jid="lory@wonderland.lit"/> <item jid="mouse@wonderland.lit"/> <item jid="sister@realworld.lit"/> </query> </iq>
<iq from=alice@wonderland.lit/pda id="ru761vd7" to=alice@wonderland.lit type="set"> <query xmlns="jabber:iq:roster"> <item jid="madhatter@wonderland.lit"/> </query> </iq>
<iq from=alice@wonderland.lit id="ru761vd7" to=alice@wonderland.lit/pda type="result"/>
具备明确的结构,一般包含原节内容,通用错误信息以及应用程序特有的错误条件和信息(可选)
XMPP协议是基于XML的协议,所以其天生提供了很好的可扩展性。咱们能够用XMPP传递各类信息,包括连接、位置信息,Web Service等。
发送XMPP节一般须要创建一个通过身份验证的XMPP会话,包括链接、流的创建、身份验证以及断开链接。
在发送任何节以前,须要创建XMPP流,在XMPP流存在以前,必须创建通往XMPP服务器的链接。
当XMPP客户端或者服务器链接到另一个XMPP服务器时,首先要查询SRV记录,该记录保存有特定域的服务器列表。查询应答中能够包含多条SRV记录,这样就能够在多个服务器中创建负载均衡链接。
若是没有找到合适的SRV记录,那么程序将试图直接链接到指定域。
一旦创建经过给定XMPP服务器的链接,XMPP流就启动了
向服务器发送<stream:stream>,就能够打开XMPP流,服务器发送响应流的起始标记<stream:stream>进行响应
创建XMPP流以后就能够来回发送各类元素
服务器发送<stream:feature>元素,列举XMPP流中支持全部功能,大多数与可用的加密和身份验证选型有关
XMPP容许进行TLS(Transport Layer Security,传输层安全)加密,并且大多数客户端默认使用该功能。
一旦服务器通告TLS支持后,客户端就会启动TLS链接并将当前套接字升级为加密套接字而不断开链接。一旦TLS加密确立,就会建立一对新的XMPP流。
XMPP中的身份验证使用SASL(Simple Authentication and Security Layers,简单身份验证与安全层)协议并支持多种身份验证机制(取决于服务器)。
一旦完成身份验证,客户端必须为链接绑定一个资源并启动一个会话,经过<bind>和<session>元素发送。
当两台服务器相互链接时,身份验证步骤稍稍不一样。
当用户结束XMPP会话后,他们终止会话并断开链接,最优雅的方式是首先发送无效出席信息,而后关闭<stream:stream>元素。
<presence type=’unavailable’> </steam:stream>