XMPP入门

本人原创,很多其它xmpp知识、ios知识、其它分享知识见:我的个人博客



简单介绍:

1、XMPP是可扩展消息与存在协议,主要用于im。

2、他是一种类似于http协议的传输数据协议。过程如:“解包装—>包装”过程。

3、在XMPP中,有三个角色:client,server。网关。  在三者之间能够进行随意两两通信。

server承担client信息记录。连接管理和信息的路由功能。网关承担与异构即时通信系统的互联互通。

4、XMPP的基本网络形式是单client通过TCP/IP连接到单server,然后传输XML。

5、他是基于C/S结构的,分布式网络。使用xml的数据格式。

6、XMPP的核心部分是由他的节构成的。

7、xmpp网络:server,client,组件,插件。

8、xmpp的jid与电子邮件地址类似。节点、域、资源。

9、xmpp主词汇表有3种节:<message>(用于在实体间交换“发后无论”消息)<presence>(传达出席状态变化并用来操纵出息订阅)<iq>(提供类似http的get和post操作的请求响应语义。).

10、xmpp会话:连接、流的建立、身份验证、会话正文、断开连接。

基本工作原理:

从一个client到还有一个client的jabber消息和数据都要通过xmpp server。

1.client连接到server。

2.server 利用本地文件夹系统的证书对其认证。

3.client制定目标地址。让server告知目标状态。

4.server查找,链接并进行相互认证。

5.client间进行交互。

XMPP节:

核心节:<message><presene><iq>

1、<stream>  xmpp以其标记開始。

2、<presence>用来表明用户状态。

能够来广播或“公布-订阅”。<status>网络状态、<show>可用状态、<priority>资源优先级。

3、<iq>一种请求/响应机制。

4、<message>用于两个jabber用户发送消息。

<body>是消息内容。他包括<subject/>(消息标题)<body/>(消息内容)<thread/>(跟踪会话线索)子标签。

简单会话:

<stream:stream>    创建一个xmpp流

<iq type=’get’>    请求elizabeth的花名冊,也就是她的全部已存储的联系人列表。

<query xmlns=’jabber:iq:roster’/>

</iq>

<presence/>             通知server她已经在线并能够訪问。  当他注意到darcy在线的时候。就会发个message节。

<message to=’darcy@pemberley.lib’

from=’ellizabaeth@longbourn.lit/ballroom’

type=’chat’>

<body>sdf</body>

</message>

<presence type=’unavailable’/>  告诉server,这是不可訪问的要关闭

</stream:stream>

节属性:

支持通用属性:from。to,type。id。

1)、from

识别此节的起始jid。这里不建议在输出的节上手工设置from属性,server会在这些节通过时加入正确的from属性,而假设错误地设置from属性会导致server拒绝整个节。

client-server中。接收到的节上没有from属性,意味着该节来源于server自身,而在server-server中,缺少from被视为是错误。

2)、to

把xml节发送到to属性指定的jid。他和from相似。

client-server流中没有to属性。那么server将如果它是有意发给server自身的消息,建议在向server自身发消息时忽略to。

假设to属性中指定的jid是一个用户,那么server有可能代表用户来处理该节。

假设目的地是一个裸jid。那么server将处理这个节。

假设目的地是一个完整的jid。那么server将直接把该节路由到该用户。

3)、type

这个属性指定了三个节的详细类型。

三个节都能够把type设置为error,表示这个节是对已接收到的同一类型的节的错误影响,不要响应类型为error的节。避免在网络上出线反馈环节。

4)、id

给节指定id来辅助识别响应。对于iq节,id是必须的,可是对于其它的节id是可选的。假设某个节是为了响应一个携带id属性的节而产生的。那么这个应答必须包括携带同样值得id值。

id必须具有唯一性。这样节的发送者就能够使用它来甄别响应了。

最简单的做法就是让id属性值在给定的流中保持唯一性,以免歧义。

在message和presence节的应答节一般仅限于报告错误,iq的应答节能够用来通知成功操作、确认命令或返回请求的数据。不管怎样client都能够使用应答节的id属性来识别与该节相关联的请求节。

在短时间内发送大量同类型的节,此时这个功能就很关键了。

由于这些节的应答可能会以乱序形式到达。

节:

1)、presence

他控制并报告实体的可訪问性。

(包含:在线,离线。  离开,请勿打搅等。  ) 他还能够用来建立和终止向其它实体公布出席订阅。

有了出席订阅通知。我们在即时通信系统中就能够在发送消息之前知道接收者是否在线。

(1)、普通的presence

此时他是不包括type属性的,假设有的话他的属性值为unavailable活着error。  在这里,type属性是没有available值得。由于我们能够通过缺省的type来设定。

用户能够通过发送不携带to属性,并直接发往server的presence节来操纵出席状态。例如以下:

<presence/>      前两个节将用户的出息状态设置为在线和离线

<presence type=‘unavailable’/>   离线

<presence>

<show>away</show>      仅仅能用在presence中,值away离开。chat聊天。end不希望被打搅。xa长期离开。  传达用户可訪问性的性质,它请求接收者的client使用这个消息来更新发送者出息状态的可视化指示器。

<status>sf</status>   一个人们可读的字符串。用户可以将其设置为可以传达出席信息的不论什么值。

聊天时,接收者的client中这个字符串一般紧挨着联系人名字显示。

</presence>

<presence>

<status>sfdf</status>

<priority>22</priority>    优先级  同一时候具有多个回话的用户能够使用优先级来指出哪一个资源应该接收到那些发往该用户裸jid的聊天消息。

</presence>

<presence>

<prioriry>11</pritority>

</presence>

(2)、扩展presence

比方将你正在听歌,心情等信息广播给其它联系人。这里用流量较大。

(3)、出席订阅

server会自己主动将出席信息广播给联系人。用户也会从全部他已经进行出席订阅的联系人那里接收到出席的状态更新。

对于好友状态的订阅:A订阅了B得出席信息。这里并非说B也订阅了A得出席信息。

订阅状态:subscribe(建立订阅),unsubscribe(取消订阅),subscribed(应答建立),unsubscribed(应答取消)。

AB订阅:

<presence from=‘a@longbourn.lit/outside’ to=‘b@pemberley.lit’ type=‘subscribe’/>

<presence from=‘b@pemberley.lit/library’ to=‘a@longbourn.lit/outside’ type=‘subscribed’/>

<presence from=‘b@pemberley.lit/library’ to=‘a@longbourn.lit’ type=‘subscribe’/>

<presence from=‘a@longbourn.lit/outside’ to=‘b@pemberley.lit/library’ type=‘subscribed’/>

(4)、定向出席

他是一种直接发给还有一个用户或其它某个实体的普通presence节。这里能够用来向那些没有进行出席订阅的实体传送出席状态信息。也就是暂时出席。

这里当发送者变成不可訪问的状态的时候。出席信息的接收者将会自己主动得到通知,即使发送者忘记显示的通知接收者。这里能够使用定向出席来暂时地掌握某个用户的可訪问性。

2)、message

从一端到还有一端发送消息。这个节属于发出后不再过问。可靠性不能保证。一旦消息发出去了。发送者就不会知道他是不是传送出去了。也不会知道到达的时间。

message演示样例:

单人聊天

<message from=‘a@netherfield.lit/frawing_room’ to=‘b@pemberley.lit’ type=‘chat’>

<body>adf</body>

</message>

多人聊天

benlent夫人向聊天室bennets@chat.merython.lit发送消息,bennet接收消息

<message from=’bennets@chat.merython.lit/mrs.bennet’ to=‘mr.bennet@longbourn.lit/study’ type=‘groupchat’>

<body>df</body>

</message>

(1)、消息类型

type指出:chat(一对一聊天),error。normal。group chat(多人聊天),headline(不支持或者不方便应答的自己主动化服务使用)。

type是能够省略的,默觉得normal。可是我们应该提供一个type值,

(2)、消息内容

<body>元素包括着该消息中人们的可读的内容。仅仅要有不同的xml:lang属性就能够使用多个<body>。

<thread>元素用来创建线索,他的内容是一个用来区分不同线索的唯一标识符。应答节应该包括与所应答的节同样的<thread>元素。 (线索:向电子邮件一样)

在消息中,能够使用XHTML-IM来给消息提供格式化,超链接,以及富媒体。也能够使用Chat State Notifications来同意用户通告对方自己正在撰写消息或有空。(qq的正在输入)

3)、iq

这个节表示的时info/query(信息与查询),他给xmpp童心提供请求和响应机制。

和http的基本工作原理想死,同意获取和设置查询。(get 和 post)

每一个节都须要有一个响应。可是这个节的必须的id将用来把响应与导致该响应的请求关联起来。

type:get。set请求节; result,error为响应节。

以下看演示样例,每一个iq节必须匹配id属性

a向server发送了一个格式错误的花名冊请求

<iq from=a@longbourn.lit/garden’ type=‘get’ id=‘roster1’>

<query cmlns=‘jabber:iq:roster’/>

</iq>

<iq to=‘a@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=a@longbourn.lit/garden’ type=‘get’ id=‘roster2’>

<query cmlns=‘jabber:iq:roster’/>

</iq>

<iq to=‘a@longbourn.lit/garden’ type=‘result’ id=‘roster2’>

<query xmlns=‘jabber:iq:roster’>

<item jid=‘b@longbourn.lit’ name=‘b’/>

<item jid=‘c@netherfield.lit’ name=‘c’/>

</query>

</iq>

a将b加入到花名冊,回复空白iq来应答成功。

<iq from=‘a@longbourn.lit/garden’ type=‘set’ id=‘roster3’>

<query xmlns=‘jabber:iq:roster’>

<item jid=“b@pemberley.lit’ name=‘b’/>

</query>

</iq>

<iq to=‘a@longbourn.lit/garden’ type=‘result’ id=‘roster3’/>

4)、error

在错误提示节中,必须将type设置为error,而且须要携带一个<error>子元素。

在error中。他的type类型为:cancel(不应该重试),continue(警告信息),modify(发送的数据须要一些改动才干够被接受),auth(通知实体在以某种方式进行身份验证之后重试),wait(报告server暂时遇到问题,稍后重发)。

在<error>中,必须包括一个错误条件作为他的子元素,也能够在<error>元素的子元素中指定应用程序的特定错误条件。还能够包括一个<text>元素来进一步指出有关该错误的具体信息。

要注意的是每一个错误条件元素都必须位于urn:ietf:params:xml:ns:xmpp-stanzas命名空间里。

<error type=‘cancel’>

<not-allowed xmlns=‘urn:ietf:params:xml:ns:xmpp-stanzas’/>  这里指出了一般性故障

<closed-node xmlns=‘http:/jabber.org/protocol/pubsub#errors’/>  给出了请缺德应用程序错误提示信息

<text xmlns=‘urn:ietf:params:xml:ns:xmpp-stanzas>dfs</text>   包括了问题描写叙述

</error>

XMPP寻址:

xmpp网络有一个或多个地址jid。  a@aaa.llit   组成:节点、域、资源(带有资源的jid是完整jid,没有资源的jid是裸jid)。当中节点和资源是可选的,域是必选的。

当中域是server等的可解析dns名称。仅仅有域组成的jid是有效的地址,表示server的地址。

当中指向域的节将由server自身处理。而且可能被路由到其它的组件或者插件上。

在本地时我们一般会识别域中的一个特定的用户,它位于@之前。本地部分还能够用来识别其它对象,多人聊天服务将每一个聊天室显示为一个jid,节点部分指向聊天室。

jid的资源部分会标识一个特定的clientxmpp链接,对于xmppclient来说。每一个链接均被指派一个资源,如 用   a@aaa.lit/study和a@aaa.lit/library  来寻址,当中资源部分也能够用来识别其它对象。在多人聊天时,jid的资源被用来识别聊天室中的一个特定的用户。

client处理裸jid的时候。server自己将处理发往client裸jid的节。

如:一条发往某个client的裸jid的消息将被转发到该用户的一个或多个已连接资源。假设该用户离线,那么就将该消息存储以后传送。可是发给完整jid的节一般会直接路由到该资源所在的client连接。能够将裸jid视为寻址用户的账户,而不是寻址该用户的某个已连接的client。

xmpp连接:

连接,流的建立,身份验证以及断开连接。

1).连接

发送节前要建立xmpp流,在流存在之前要建立通往xmppserver的连接。

client和server利用域名系统将server的域名解析成一个可以连接的地址。电子邮件服务特别的使用邮件交换台记录来提供处理特定域邮件的server列表。

这样一个知名server地址就不用处理每一项服务请求了。

电子邮件在dns中有特殊的对待。如今服务记录srv可用来为随意服务提供类似的功能。

当xmppclient或server连接到还有一个xmppserver的时候,首先要在server域中查询适当的srv记录。查询应答中可能包括多条srv记录,这样就能够在多台server间建立负载均衡链接。

当没有找到合适的srv记录的时候。应用程序试着直接连接到给定域。大多数库也能够显式制定要连接的server。

2).流的建立

向server发送起始元素<stream:stream>,就能够打开xmpp流。

server通过发送响应流的起始标记<stream:stream>进行响应。

server先发送<stream:features>元素,具体列举xmpp流中支持的全部功能。

这些功能大多数与可用的加密和身份验证选项有关。

client发给server

<?

xml version=’1.0′?>

<stream:stream xmlns=’jabber:client’

xmlns:straem=’http://ethrx.jabber.org/streams’

version=’1.0′

to=’pemberley.lit’>

server应答

<?xml version=’1.0′?

>

<stream:stream xmlns=’jabber:client’

xmlns:stream=’http://etherx.jabber.org/streams’

version=’1.0′

from=’pemberley.lit’

id=’dddd’

xml:lang=’en’>

<stream:features>

<stream:freatures>

<starttls xmlns=’urn:ietf:params:xml:ns:xmpp-tls’/>

<compression xmlns=’http://jabber.org/features/compress’>

<method>zlib</method>

</compression>

<mechanisms xmlns=’urn:ietf:params:xml:ns:xmpp-sasl’>                     <mechanism>DIGEST-MD5</mechanism>

<mechanism>PLAIN</mechanism>

</mechanisms>

</stream:features>

依据数据交换信息指导pemberley.orgserver支持TLS。流压缩zlib等。

在两台服务器间建立xmpp流的过程同样。可是 jabber:client换成 jabber:server才干够。

3).身份验证

xmpp能够进行tls传输层安全加密,而且大多数client默认使用。

server支持tls加密后。client就会启动tls链接。并将当前套接字升级为一个加密套接字。

创建一对新的xmpp流。

xmpp身份验证使用sasl 简单身份验证与安全层协议,并支持多种身份验证机制。server通提供明文验证和基于md5摘要的验证,可是某些server还支持通过kerberos或特殊令牌来验证。

完毕身份验证后,client必选为该链接绑定一个资源并启动一个会话。假设用户正在线路上查看xmpp流量,就会看到<bind><session>元素被发送出去。(在<iq>中)  假设client没有提供绑定的资源,那么server将为其选定一个。

当两台server相互连接的时候,server交换并验证tls证书。或者接受server使用某种回拨协议通过dns来验证发送者身份。

4).连接断开

当用户结束xmpp会话的时候,他们终止会话并断开连接。

最有礼貌的终止会话的方式是:先发送无效出席信息。然后关闭<stream:stream>元素。

通过发送最后的无效出席信息,用户的联系人可以得知该用户离开的原因。

<presence type=’unavailable’/>

</stream:stream>

然后,server终止发往client的流。

上一篇:使用ffmpeg转码时遇到aac报错


下一篇:nginx代理部署Vue与React项目