XMPP 简单介绍

本小节将简要介绍 XMPP,它的起源。以及为何它是一个适合实时 web 通信的协议。您将检查 XMPP 通信设置的组件,并查看展示这些组件怎样使用的演示样例。

Web 标准和 XMPP

XMPP 是一组基于 XML 的技术。用于实时应用程序。最初。XMPP 作为一个框架开发。目标是支持企业环境内的即时消息传递和联机状态应用程序。当时的即时消息传递网络是私有的,很不适合企业使用。比如。AOL Instant Messenger 不能针对公司内的安全通信进行调整。虽然存在一些商业解决方式,但它们固定的特性集通常不能进行调整,以满足组织的特殊需求。XMPP,当时名为 Jabber,同意组织构建自己的定制工具来促进实时通信。并同意安装现成的第三方解决方式。

XMPP 是一个分散型通信网络,这意味着,仅仅要网络基础设施同意,不论什么 XMPP 用户都能够向其它不论什么 XMPP 用户传递消息。

多个 XMPP server也能够通过一个专门的 “server-server” 协议相互通信。提供了创建分散型社交网络和协作框架的有趣可能性。但这个主题已超出了本教程的讨论范围。

顾名思义,XMPP 可用于满足广泛的、对时间敏感的特性要求。实际上。Google Wave。一个大型多用户协作环境。将 XMPP 作为其联合协议的基础。虽然 XMPP 的出现是为了满足 “个人-个人” 即时消息传递的要求。但它全然不必局限于此任务。

 

回页首

XMPP 通信的结构

要促进消息传递,每一个 XMPP client用户必须拥有一个全局惟一标识符。基于历史原因。这些标识符称为 Jabber IDs。或称为 JIDs。

鉴于这个协议的分布式特征。重要的是 JID 应包括联系用户所需的全部信息:不存在将用户链接到他们连接到的server的中央知识库。

JID 的结构类似于电子邮件地址(但不要求 JID 同一时候也是有效的电子邮件收件人)。

client和server节点。我将它们统称为 XMPP 实体,都拥有 JIDs。SomeCorp 公司的员工 John Doe 可能拥有 JIDJohn.Doe@somecorp.com

这里,somecorp.com 是 SomeCorp 公司的 XMPP server的地址。John.Doe 是 John Doe 的username。

JIDs 还拥有连接到它们的资源。

这同意在一个 XMPP 实体标识符之外进一步处理细粒度。比如,虽然上面的演示样例整体上可以表示 John Doe。但 John.Doe@somecorp.com/Work 可以用于将数据发送到与他的工作相关的工具。

这些资源能够採用随意用户定义的名称。一个 XMPP 实体能够拥有随意数量的资源。除了能够是上下文依赖的外,它们还能够绑定到设备、工具或工作站。对于您的 Pingstream 演示样例,web 网站的每一个訪问者都将作为同一个用户登录 XMPP server。但他们拥有不同的资源。

 

回页首

通信类别

使用 XMPP 的实时消息传递系统包括三大通信类别:

  • 消息传递。当中数据在有关各方之间传输;
  • 联机状态,它同意用户广播其在线状态和可用性;
  • 信息/查询请求。它同意 XMPP 实体发起请求并从还有一个实体接收响应。

这些类别是互补的。比如。假设用户或实体离线(虽然在很多用例中,理想的状态是server在用户返回之前一直持实用户的消息),则没有将数据发送给用户或发起一个实体的信息/查询请求的点。

这些消息中的每一条都将通过一个完整的 XML 传递 — XML 节是以 XML 表达的独立信息项。

这三种类型的 XMPP 节都拥有下面公共属性:

  • from:源 XMPP 实体的 JID;
  • to:目标接收者的 JID;
  • id:这次对话的可选标识符;
  • type:节的可选子类型。
  • xml:lang:假设内容是人们可读的,则为消息语言的描写叙述。

基于 XMPP 的传输数据发生在一些 XML 流上。默认在port 5222 上操作。这些 XML 流实际上是两个完整的 XML 文档。每一个文档相应一个通信方向。

一旦会话建立。stream 元素将打开。

这个元素将封装整个通信文档。

然后。一些节被注入这个文档的第二层。

最后,一旦通信结束,stream 元素将关闭,形成一个完整的文档。

比如。清单 1 展示了一个 stream 元素,它建立了从client到server的通信。

清单 1. 建立从client到server的通信的 stream 标记

<stream:stream from="[server]" id="[unique ID over conversation]"
xmlns="jabber:client" xmlns:stream="http://etherx.jabber.org/streams" version="1.0">
 

回页首

消息

一旦通信建立,client就能使用 message 元素将消息发送到还有一个用户,message 元素包括下面随意子元素:

  • subject:一个可读的字符串。表示消息主题。
  • body:一个可读的字符串,表示消息体。

    假设每一个消息体标记都拥有一个不同的 xml:lang 值,那么能够包括多个消息体标记。

    xml:lang 是惟一可能的属性。)

  • thread:一个惟一标识符。表示一个消息线程。client软件能够使用这个子元素将相关消息串联在一起。

可是,消息也能够很easy,如 清单 2 所看到的:

清单 2. 例子消息

<message from="sendinguser@somedomain" to="recipient@somedomain" xml:lang='en'>
<body>
Body of message
</body>
</message>

对于提供实时 web 界面而言,消息节是最实用的节。

“公布-订阅” 模型 — 在实时 web 应用程序中使用消息来数据传输的一种替代方法 — 将稍后介绍。

 

回页首

信息/查询

信息/查询节拥有广泛的功能。一个样例就是 “公布-订阅” 模型,在该模型中,公布者通知server某个特定资源进行了更新。server则通知已选择订阅这些通知并拥有适当授权的全部 XMPP 用户。

来自公布者的一系列项目被编码为一些节。格式为基于 XML 的 Atom 公布格式。

每一个项目都包括在一个 item 元素内,然后合并到一个 pubsub 元素中。最后成为一个信息/查询节。在 清单
3
(选自 XMPP 公布-订阅规范)中,Shakespeare's Hamlet(JID 为 hamlet@denmark.lit/blogbot)用他著名的独白公布一个更新到 pubsub.shakespeare.lit pubsub 更新节点:

清单 3. 对 pubsub.shakespeare.lit pubsub 更新节点的更新

<iq type="set"
from="hamlet@denmark.lit/blogbot"
to="pubsub.shakespeare.lit"
id="pub1">
<pubsub xmlns="http://jabber.org/protocol/pubsub">
<publish node="princely_musings">
<item>
<entry xmlns="http://www.w3.org/2005/Atom">
<title>Soliloquy</title>
<summary>
To be, or not to be: that is the question:
Whether 'tis nobler in the mind to suffer
The slings and arrows of outrageous fortune,
Or to take arms against a sea of troubles,
And by opposing end them?
</summary>
<link rel="alternate" type="text/html"
href="http://denmark.lit/2003/12/13/atom03"/>
<id>tag:denmark.lit,2003:entry-32397</id>
<published>2003-12-13T18:30:02Z</published>
<updated>2003-12-13T18:30:02Z</updated>
</entry>
</item>
</publish>
</pubsub>
</iq>

信息/查询节也用于请求一个特定 XMPP 实体的有关信息。比如,在 清单 4 中的节中,boreduser@somewhere 正在查找friendlyuser@somewhereelse 拥有的公共项目。

清单 4. 用户查找由 friendlyuser@somewhereelse 拥有的公共项目

<iq type="get"
from="boreduser@somewhere"
to="friendlyuser@somewhereelse"
id="publicStuff">
<query xmlns="http://jabber.org/protocol/disco#items"/>
</iq>

反过来,friendlyuser@somewhereelse 使用一列可被订阅到使用 “公布-订阅” 的项目进行响应,如 清单 5 所看到的:

清单 5. 使用一列项目响应

<iq type="result"
from="friendlyuser@somewhereelse"
to="boreduser@somewhere"
id="publicStuff">
<query xmlns="http://jabber.org/protocol/disco#items">
<item jid="stuff.to.do"
name="Things to do"/>
<item jid="stuff.to.not.do"
name="Things to avoid doing"/>
</query>
</iq>

在 清单 5 中的信息/查询节中的每一个返回项目都拥有一个能够订阅到的 JID。信息/查询还同意超出本教程范围的广泛的server信息请求。

它们中的很多在针对多server环境的 web 应用程序上下文中实用,或者作为复杂的分散型协作框架的基础。

 

回页首

联机状态

联机状态信息包括在一个联机状态(presence)节中。假设 type 属性省略。那么 XMPP client应用程序假定用户在线且可用。

否则,type 可设置为 unavailable,或者特定于 pubsub 的值:subscribesubscribedunsubscribe 和unsubscribed。它也能够是针对还有一个用户的联机状态信息的一个错误或探针。

一个联机状态节能够包括下面子元素:

  • show:一个机器可读的值。表示要显示的在线状态的整体类别。这能够是 away(临时离开)、chat(可用且有兴趣交流)、dnd(请勿打搅)、或 xa(长时间离开)。
  • status:一个可读的 show 值。

    该值为用户可定义的字符串。

  • priority:一个位于 -128 到 127 之间的值。定义消息路由到用户的优先顺序。假设值为负数,用户的消息将被扣留。

比如。清单 6 中的 boreduser@somewhere 能够用这个节来表明聊天意愿:

清单 6. 例子联机状态通知

<presence xml:lang="en">
<show>chat</show>
<status>Bored out of my mind</status>
<priority>1</priority>
</presence>

注意 from 属性此处省略。

还有一个用户 friendlyuser@somewhereelse 能够通过发送 清单 7 中的节来探測 boreduser@somewhere 的状态:

清单 7. 探測用户状态

<presence type="probe" from="friendlyuser@somewhereelse" to="boreduser@somewhere"/>
Boreduser@somewhere's server would then respond with a tailored presence response:
<presence xml:lang="en" from="boreduser@somewhere" to="friendlyuser@somewhereelse">
<show>chat</show>
<status>Bored out of my mind</status>
<priority>1</priority>
</presence>

这些联机状态值源自 “个人-个人” 消息传递软件。show 元素的值 — 通经常使用于确定将向其它用户显示的状态图标 — 在聊天应用程序之外怎样使用如今还不清楚。

状态值可能会在微博工具中找到用武之地。比如,Google Talk(一个 XMPP 聊天服务)中的用户状态字段的更改能够被导入为 Google Buzz 中的微博条目。

还有一种可能性就是将状态值用作每用户应用程序状态数据的携带者。

虽然此规范将状态定义为可读,但没有什么能够阻止您在那里存储随意字符串来满足您的要求。

对于某些应用程序而言。它能够不是可读的,或者。它能够携带微格式形态的数据负载。

您能够为一个 XMPP 实体拥有的每一个资源独立设置联机状态信息。以便訪问和接收连接到一个应用程序中的单个用户的全部工具和上下文的数据仅仅需一个用户帐户。每一个资源都能够被分配一个独立的优先级;XMPP server将首先尝试将消息传递给优先级较高的资源。

 

回页首

XMPP 使用 BOSH 越过 HTTP

要通过使用 JavaScript 的 XMPP 进行通信的 web 应用程序必须符合一些特殊要求。出于安全考虑。不同意 JavaScript 从 web 页面的域与不同域上的多个server通信。假设您的 web 应用程序界面被托管在 application.mydomain.com。全部 XMPP 通信也必须发生在 application.mydomain.com

防火墙是还有一个问题所在。理想情况下,假设您将 XMPP 用作您的 web 界面的实时元素的基础,那么您希望它对防火墙后面的用户有效。可是。公司防火墙通常仅仅对少数几个协议开放几个port,以便同意 web 数据、电子邮件和类似的通信通过。默认情况下,XMPP 使用port 5222,这非常可能是公司防火墙阻止的port。

如果您知道您的用户前面的防火墙在port 80 上同意 HTTP(这是用于訪问 web 的默认协议和port)。理想情况是您的 XMPP 通信可以越过该port上的 HTTP。可是,HTTP 的设计并不针对持续连接。

web 的架构不同于实时数据所需的通信架构。

以下我们看看 Bidirectional-streams Over Synchronous HTTP (BOSH) 的标准,该标准为双向同步数据提供一个模拟层。

借助这个标准,能够与一个 XMPP server建立一个较长的 HTTP 连接(时长一分钟或两分钟)。

假设新数据在那个期间到达,则 HTTP 请求返回数据并关闭。否则,该请求仅仅是失效。无论是哪种情况,一旦一个请求关闭,还有一个请求将又一次建立。虽然结果是对一个 web server的一系列反复连接,但它是一个比 Ajax 轮询更有效的数量级。特别是由于连接到的是一个专业server而不是直接连接到
web 应用程序。

BOSH 上的 XMPP 同意 web 应用程序通过一个原生连接持续与 XMPP server通信。client通过port 80 上的 HTTP 上的一个标准 URL 连接。然后,web server将这个连接代理到由 XMPP server操作的一个不同port — 一般是 7070 — 上的 HTTP URL。这样,不管何时数据被发送到 XMPP server,web 应用程序仅仅需使用一些资源,而 web client能够使用通常支持的 web 标准从防火墙后操作。维持 BOSH 的较长 HTTP 轮询的开销主要由 XMPP server而不是 web
server或 web 应用程序承担。

web server和 XMPP server都不会受到与使用 JavaScript 进行通信一样的域限制。正是由于这一点。消息才可以被发送到其它 XMPP server和client。

如今,您理解了 XMPP 怎样适合实时 web,能够下载并设置它。以便開始创建这个 Pingstream 应用程序。


XMPP学习及使用1的更多相关文章

  1. Openfire/XMPP学习之——一个简单的Smack样例

    昨天讲了Openfire的搭建和配置,今天来讲一下Smack.如果对如何搭建和配置Openfire的,可以参考Openfire/XMPP学习之——Openfire的安装.配置. Smack是一个开源, ...

  2. XMPP学习——3、XMPP协议学习补充

    流基础 两个基本概念,使得XMPP实体之间的小的结构化信息有效载荷能快速地进行异步交换:XML流和XML节.这些术语的定义如下. XML流的定义: XML流是一个容器,用于任何两个实体通过网络进行XM ...

  3. Xmpp学习之Android-smack入门指导

    Xmpp学习之Android-smack入门指导 版权声明:本文为博主原创文章,未经博主允许不得转载. 转载请表明出处:http://www.cnblogs.com/cavalier-/p/69404 ...

  4. Xmpp学习之Smack发送消息JID变乱码

    Xmpp学习之Smack发送消息JID变乱码 版权声明:本文为博主原创文章,未经博主允许不得转载. 转载请表明出处:http://www.cnblogs.com/cavalier-/p/6947723 ...

  5. 搭建XMPP学习环境

    XMPP(Extensible Messaging and Presence Protocol,前称Jabber)是一种以XML为基础的开放式IM协议.xmpp被人熟知,google talk肯定有一 ...

  6. XMPP学习——2、用户登录

    最近在学习XMPP的使用,打算完成一个完整较为完整地Demo示例,通过这个示例掌握xmpp的使用与开发.同时打算在这个示例中学习使用一下其他的开源类库,在此作为记录学习. 包括服务器端--Openfi ...

  7. XMPP学习记录之实战篇

    在学习iOS以来一直想要研究即时聊天方面的技术,因工作原因此计划一直搁浅,近日偷得时闲开始着手与XMPP的学习.在学习之前我一直认为XMPP对我来说是一个很有难度的挑战,在了解了协议的具体形式后,才发 ...

  8. XMPP学习——1、介绍

    XMPP(Extensible Messaging and Presence Protocol,前称Jabber[1])是一种以XML为基础的开放式实时通信协议,是经由互联网工程工作小组(IETF)通 ...

  9. Xmpp学习之Asmack取经-asmack入门(一)

    1.XMPPConnection:它主要是用来创建一个跟XMPP服务端的Socket连接.它是与Jabber服务端的默认连接并且已经在RFC 3920中精确定义过了.示例如下: XMPPConnect ...

随机推荐

  1. SpringBoot下配置FreeMarker配置远程模版

    需求产生原因 要求在同一个接口中,根据不同的参数,返回不同的视图结果 所有的视图中的数据基本一致 要求页面能静态化,优化SEO 例如:A接口返回客户的信息 客户A在调用接口时,返回其个性化定制的页面A ...

  2. HTTPS 建立连接的详细过程

    HTTPS是在HTTP的基础上和ssl/tls证书结合起来的一种协议,保证了传输过程中的安全性,减少了被恶意劫持的可能.很好的解决了解决了http的三个缺点(被监听.被篡改.被伪装) 对称加密和非对称 ...

  3. HDnoip2017题解

    那么,作为一名初入信息竞赛的选手,我也试着开始用博客记录自己的学习历程,那么这篇文章先简单介绍一下我自己吧. 本人开始学习信息学大概以来,主要都是用的C++,所以对其他语言并不是十分熟悉.2016我还 ...

  4. JavaScript中的内存泄漏以及如何处理

    随着现在的编程语言功能越来越成熟.复杂,内存管理也容易被大家忽略.本文将会讨论JavaScript中的内存泄漏以及如何处理,方便大家在使用JavaScript编码时,更好的应对内存泄漏带来的问题. 概 ...

  5. TensorFlow[1]:概念和简例

    简介 TensorFlow是一个实现机器学习算法的接口,也是执行机器学习算法的框架.使用数据流式图规划计算流程,可以将计算映射到不同的硬件和操作系统平台. 主要概念 TensorFlow的计算可以表示 ...

  6. Vim常用操作-合并行。

    刚接触 Vim 会觉得它的学习曲线非常陡峭,要记住很多命令.所以这个系列的分享,不会教你怎么配置它,而是教你怎么快速的使用它. 在开发时为了代码美观,经常会把属性用换行的方式显示. <el-di ...

  7. lumen 中间件详解

    我来给大家,讲解一下lumen中的中间件,高手勿喷. 首先,我们看下lumen中文档中的写法,我这里看的是5.3中文文档.https://lumen.laravel-china.org/docs/5. ...

  8. Winform界面中实现通用工具栏按钮的事件处理

    在一个给客户做的项目中,界面要求修改增加通用工具栏按钮的事件处理,也就是在主界面中放置几个固定的功能操作按钮,打开不同的页面的时候,实现对应页面的功能处理,这种和我标准的界面处理方式有所不同,标准的列 ...

  9. ASP.NET Core 一步步搭建个人网站(持续更新中~~~)

    摘要 ASP.NET Core2.0发布有一阵子了,这是.NET 开源跨平台的一个重大里程碑, 也意味着比1.0版本要更加成熟.目前.net core具有开源.跨平台.灵活部署.模块化架构等等特性,吸 ...

  10. JavaScript(五):函数(闭包,eval)

    1.函数的申明:三种方法: function命令 函数表达式:变量赋值 Function构造函数 //method 1: function命令 function test(){ console.log ...