XMPP学习及使用1

XMPP 简介

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

Web 标准和 XMPP

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

XMPP 是一个分散型通信网络,这意味着,只要网络基础设施允许,任何 XMPP 用户都可以向其他任何 XMPP 用户传递消息。多个 XMPP 服务器也可以通过一个专门的 “服务器-服务器” 协议相互通信,提供了创建分散型社交网络和协作框架的有趣可能性,但这个主题已超出了本教程的讨论范围。

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

回页首

XMPP 通信的结构

要促进消息传递,每个 XMPP 客户端用户必须拥有一个全局惟一标识符。基于历史原因,这些标识符称为 Jabber IDs,或称为 JIDs。鉴于这个协议的分布式特征,重要的是 JID 应包含联系用户所需的所有信息:不存在将用户链接到他们连接到的服务器的中央知识库。JID 的结构类似于电子邮件地址(但不要求 JID 同时也是有效的电子邮件收件人)。

客户端和服务器节点,我将它们统称为 XMPP 实体,都拥有 JIDs。SomeCorp 公司的员工 John Doe 可能拥有 JID[email protected]。这里,somecorp.com 是 SomeCorp 公司的 XMPP 服务器的地址,John.Doe 是 John Doe 的用户名。

JIDs 还拥有连接到它们的资源。这允许在一个 XMPP 实体标识符之外进一步处理细粒度;例如,尽管上面的示例总体上能够表示 John Doe,但 [email protected]/Work 可以用于将数据发送到与他的工作相关的工具。

这些资源可以采用任意用户定义的名称,一个 XMPP 实体可以拥有任意数量的资源。除了可以是上下文依赖的外,它们还可以绑定到设备、工具或工作站。对于您的 Pingstream 示例,web 站点的每个访问者都将作为同一个用户登录 XMPP 服务器,但他们拥有不同的资源。

回页首

通信类别

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

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

这些类别是互补的。例如,如果用户或实体离线(尽管在许多用例中,理想的状态是服务器在用户返回之前一直持有用户的消息),则没有将数据发送给用户或发起一个实体的信息/查询请求的点。这些消息中的每一条都将通过一个完整的 XML 传递 — XML 节是以 XML 表达的独立信息项。

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

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

基于 XMPP 的数据传输发生在一些 XML 流上,默认在端口 5222 上操作。这些 XML 流实际上是两个完整的 XML 文档,每个文档对应一个通信方向。一旦会话建立,stream 元素将打开。这个元素将封装整个通信文档。然后,一些节被注入这个文档的第二层。最后,一旦通信结束,stream 元素将关闭,形成一个完整的文档。

例如,清单 1 展示了一个 stream 元素,它建立了从客户端到服务器的通信。

清单 1. 建立从客户端到服务器的通信的 stream 标记

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

回页首

消息

一旦通信建立,客户端就能使用 message 元素将消息发送到另一个用户,message 元素包含以下任意子元素:

  • subject:一个可读的字符串,表示消息主题。
  • body:一个可读的字符串,表示消息体。如果每个消息体标记都拥有一个不同的 xml:lang 值,那么可以包含多个消息体标记。(xml:lang 是惟一可能的属性。)
  • thread:一个惟一标识符,表示一个消息线程。客户端软件可以使用这个子元素将相关消息串联在一起。

但是,消息也可以非常简单,如 清单 2 所示:

清单 2. 样例消息

<message from="[email protected]" to="[email protected]" xml:lang=‘en‘>
  <body>
    Body of message
  </body>
</message>

对于提供实时 web 界面而言,消息节是最有用的节。“发布-订阅” 模型 — 在实时 web 应用程序中使用消息来传输数据的一种替代方法 — 将稍后介绍。

回页首

信息/查询

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

来自发布者的一系列项目被编码为一些节,格式为基于 XML 的 Atom 发布格式。每个项目都包含在一个 item 元素内,然后合并到一个 pubsub 元素中,最后成为一个信息/查询节。在 清单
3
(选自 XMPP 发布-订阅规范)中,Shakespeare‘s Hamlet(JID 为 [email protected]/blogbot)用他著名的独白发布一个更新到 pubsub.shakespeare.lit pubsub 更新节点:

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

<iq type="set"
    from="[email protected]/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 中的节中,[email protected] 正在查找[email protected] 拥有的公共项目。

清单 4. 用户查找由 [email protected] 拥有的公共项目

<iq type="get"
    from="[email protected]"
    to="[email protected]"
    id="publicStuff">
  <query xmlns="http://jabber.org/protocol/disco#items"/>
</iq>

反过来,[email protected] 使用一列可被订阅到使用 “发布-订阅” 的项目进行响应,如 清单 5 所示:

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

<iq type="result"
    from="[email protected]"
    to="[email protected]"
    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。信息/查询还允许超出本教程范围的广泛的服务器信息请求。它们中的许多在针对多服务器环境的 web 应用程序上下文中有用,或者作为复杂的分散型协作框架的基础。

回页首

联机状态

联机状态信息包含在一个联机状态(presence)节中。如果 type 属性省略,那么 XMPP 客户端应用程序假定用户在线且可用。否则,type 可设置为 unavailable,或者特定于 pubsub 的值:subscribesubscribedunsubscribe 和unsubscribed。它也可以是针对另一个用户的联机状态信息的一个错误或探针。

一个联机状态节可以包含以下子元素:

  • show:一个机器可读的值,表示要显示的在线状态的总体类别。这可以是 away(暂时离开)、chat(可用且有兴趣交流)、dnd(请勿打扰)、或 xa(长时间离开)。
  • status:一个可读的 show 值。该值为用户可定义的字符串。
  • priority:一个位于 -128 到 127 之间的值,定义消息路由到用户的优先顺序。如果值为负数,用户的消息将被扣留。

例如,清单 6 中的 [email protected] 可以用这个节来表明聊天意愿:

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

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

注意 from 属性此处省略。

另一个用户 [email protected] 可以通过发送 清单 7 中的节来探测 [email protected] 的状态:

清单 7. 探测用户状态

<presence type="probe" from="[email protected]" to="[email protected]"/>
[email protected]‘s server would then respond with a tailored presence response:
<presence xml:lang="en" from="[email protected]" to="[email protected]">
  <show>chat</show>
  <status>Bored out of my mind</status>
  <priority>1</priority>
</presence>

这些联机状态值源自 “个人-个人” 消息传递软件。show 元素的值 — 通常用于确定将向其他用户显示的状态图标 — 在聊天应用程序之外如何使用现在还不清楚。状态值可能会在微博工具中找到用武之地;例如,Google Talk(一个 XMPP 聊天服务)中的用户状态字段的更改可以被导入为 Google Buzz 中的微博条目。

另一种可能性就是将状态值用作每用户应用程序状态数据的携带者。尽管此规范将状态定义为可读,但没有什么能够阻止您在那里存储任意字符串来满足您的要求。对于某些应用程序而言,它可以不是可读的,或者,它可以携带微格式形态的数据负载。

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

回页首

XMPP 使用 BOSH 越过 HTTP

要通过使用 JavaScript 的 XMPP 进行通信的 web 应用程序必须符合一些特殊要求。出于安全考虑,不允许 JavaScript 从 web 页面的域与不同域上的多个服务器通信。如果您的 web 应用程序界面被托管在 application.mydomain.com,所有 XMPP 通信也必须发生在 application.mydomain.com

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

假设您知道您的用户前面的防火墙在端口 80 上允许 HTTP(这是用于访问 web 的默认协议和端口)。理想情况是您的 XMPP 通信能够越过该端口上的 HTTP。但是,HTTP 的设计并不针对持续连接。web 的架构不同于实时数据所需的通信架构。

下面我们看看 Bidirectional-streams Over Synchronous HTTP (BOSH) 的标准,该标准为双向同步数据提供一个模拟层。借助这个标准,可以与一个 XMPP 服务器建立一个较长的 HTTP 连接(时长一分钟或两分钟)。如果新数据在那个期间到达,则 HTTP 请求返回数据并关闭;否则,该请求只是失效。不管是哪种情况,一旦一个请求关闭,另一个请求将重新建立。尽管结果是对一个 web 服务器的一系列重复连接,但它是一个比 Ajax 轮询更有效的数量级,特别是因为连接到的是一个专业服务器而不是直接连接到
web 应用程序。

BOSH 上的 XMPP 允许 web 应用程序通过一个原生连接持续与 XMPP 服务器通信。客户端通过端口 80 上的 HTTP 上的一个标准 URL 连接。然后,web 服务器将这个连接代理到由 XMPP 服务器操作的一个不同端口 — 通常是 7070 — 上的 HTTP URL。这样,无论何时数据被发送到 XMPP 服务器,web 应用程序只需使用一些资源,而 web 客户端可以使用通常支持的 web 标准从防火墙后操作。维持 BOSH 的较长 HTTP 轮询的开销主要由 XMPP 服务器而不是 web
服务器或 web 应用程序承担。web 服务器和 XMPP 服务器都不会受到与使用 JavaScript 进行通信一样的域限制,正是因为这一点,消息才能够被发送到其他 XMPP 服务器和客户端。

现在,您理解了 XMPP 如何适合实时 web,可以下载并设置它,以便开始创建这个 Pingstream 应用程序。

时间: 2024-11-07 20:36:26

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

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

1.XMPPConnection:它主要是用来创建一个跟XMPP服务端的Socket连接.它是与Jabber服务端的默认连接并且已经在RFC 3920中精确定义过了.示例如下: XMPPConnection connection=new XMPPConnection(configuration); connection.connect(); 2.ConnectionConfiguration:当我们要建立跟服务端的连接时通过它来进行一些配置一些连接参数.例如,你可以通过它来配置trustore文

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

昨天讲了Openfire的搭建和配置,今天来讲一下Smack.如果对如何搭建和配置Openfire的,可以参考Openfire/XMPP学习之——Openfire的安装.配置. Smack是一个开源,易于使用的XMPP客户端类库.Smack API, 是一个 Java 的XMPP Client Library,也是由Jive Software开发. 优点:编程简单. 缺点:API并非为大量并发用户设计,每个客户要1个线程,占用资源大,1台机器只能模拟有限(数千个)客户.Smack是一个用 jav

XMPP学习记录之实战篇

在学习iOS以来一直想要研究即时聊天方面的技术,无奈工作或时间原因一直搁浅此计划,近日偷得时闲开始着手与XMPP的学习.在学习之前我一直认为XMPP对我来说是一个很有技术的挑战,在了解了协议的具体形式后,才发觉其实技术的难度只在跟你底层代码原理的掌握程度的熟练度有关,说通俗一点,很多东西其实我们都会,只是在各个框架或技术中我们没有考虑到的东西别人都考虑周全!比如你若对socket有一定的了解并懂得xml数据解析那你就可以看懂大部分的xmpp文档!所以只要掌握了相对来说底层的一些技术那么对于学习于

XMPP学习

XMPP通信学习 http://blog.csdn.net/kangx6/article/details/7744304 在这个网站上发现了一个关于XMPP的教程,很好很强大.虽然我自己没有组建服务器,但是通过对它的学习,大概掌握了它的过程. 首先是下载XMPPFramework 这个第三方,按照链接的教程导入,也可以下载它的demo 如果没找到,评论会给出demo的地址 本文按照demo的xun'xu'an循序讲 导入XMPPFramework 后  要先确定和host主机链接上了,然后才能收

RFC 6120 XMPP学习笔记

XMPP - Extensible Messaging and Presence Protocol 1. 中文版3920 http://wiki.jabbercn.org/RFC3920 2. 大部分客户端通过 TCP 连接直接连到服务器,并通过XMPP获得由服务器以及联合服务器所提供的全部功能.多个不同资源(比如不同的设备和地点)的客户端可以同时登陆并且并发的连接到一个服务器,每个不同资源的客户端通过XMPP地址的资源标识符来区分(比如<[email protected]/home> 和 &

iOS xmpp学习 - 环境搭建(配置mysql与openfire服务端)

1> 安装数据库mysql -安装mysql-5.7.12-osx10.11-x86_64.dmg -上面这个mysql是新版本的, 只有一个主安装程序包含全部功能 -在老版本的mysql中会有3个需要安装的程序 *mysql-版本号-要求系统版本-x86_64.dmg     // 这个是主安装程序 *MySQL.prefPane     // 这个是系统偏好管理, 就是在'系统偏好设置'里面添加mysql管理程序 *MySQLStartupItem.pkg     // 自动启动MySQL服

Openfire/XMPP学习之——Openfire的安装、配置

一.Openfire下载: 官方下载:http://www.igniterealtime.org/downloads/index.jsp 在官方下载站点,可以获取Windows.Linux.Mac三种系统的安装文件,我们这里主要讲的是Windows系统的配置,忽略其它系统吧.对于Windows系统来讲,安装文件又分为exe和zip的,个人推荐exe的安装文件,只需要双击->安装就行了,省时省力.对于zip格式的,百度的使用方法是:解压,复制文件到C:\Program Files\目录下即可.这个

Android基于XMPP Smack及Openfire学习笔记(1)

之前开发的项目中实用到IM聊天功能.可是这块功能公司有专门的IM团队来开发,由他们开发好后.直接接入到我们APP中.我參与写IM相关功能非常地少,所以也一直想学习相关知识 . 眼下Android主要用的是XMPP协议及OPenfireserver来实现IM功能,我也从这块入手学习.也感谢全部分享资料让我有机会学习的同行们. 如今正式開始啦. 第一步:搭建Openfireserver: Openfire工具下载地址:http://www.igniterealtime.org/downloads/i

xmpp协议学习笔记

本文是根据xmpp协议视频教程的学习笔记. 每一个客户端使用JID(jabber identifier)来作为身份标识 ,格式为[user"@"]domain["/"resource],其中 domain:服务器域名: user:用户名: resource:属于用户的位置或设备,比如是手机还是电脑     一个用户可以同时以多种资源与统一个XMPP服务器连接,完整的JID例子:[email protected]/iphone6s     stanza的通用属性:fr