引言

  目前互联网产品使用的即时通信协议有这几种:即时信息和空间协议(IMPP)、空间和即时信息协议(PRIM)、针对即时通讯和空间平衡扩充的进程开始协议SIP(SIMPLE)以及XMPP。PRIM与XMPP、SIMPLE类似,但已经不再使用了。

  本次要讲的是XMPP,由Openfire实现.

  1、Openfire与XMPP

  Openfire是开源的实时协作服务器(RTC),它是基于公开协议XMPP(RFC-3920),并在此基础上实现了XMPP-IM(RFC-3921),扩展了IM功能,对实施协作的各种场景做较全面的考虑,如用户在线状态切换、消息订阅、通知等等,因此可以用来搭建即时通信服务器,其搭建的方法也很简易。

  RFC-3920与RFC-3921的说明:

  (1)RFC-3920:XMPP的核心。定义了XMPP协议框架下应用的网络架构,引入了XMLStream(XML流)与XMLStanza(XML节),并规定XMPP协议在通信过程中使用的XML标签。使用XML标签从根本上说是协议开放性与扩展性的需要。此外,在通信的安全方面,把TLS 安全传输机制与SASL 认证机制引入到内核,与XMPP进行无缝的连接,为协议的安全性、可靠性奠定了基础。Core文档还规定了错误的定义及处理、XML 的使用规范、JID(Jabber Identifier,Jabber 标识符)的定义、命名规范等等。所以这是所有基于XMPP协议的应用都必需支持的文档。

  (2)RFC-3921:用户成功登陆到服务器之后,发布更新自己的在线好友管理、发送即时聊天消息等业务。所有的这些业务都是通过三种基本的XML 节来完成的:IQ Stanza(IQ 节), Presence Stanza(Presence 节), Message Stanza(Message 节)。RFC3921 还对阻塞策略进行了定义,定义是多种阻塞方式。可以说,RFC3921 是RFC3920的充分补充。两个文档结合起来,就形成了一个基本的即时通信协议平台,在这个平台上可以开发出各种各样的应用。

  2、Openfire的特点:

 (1)超强的扩展能力

  XMPP协议,继承了在XML灵活的扩展性,通过扩展发送扩展信息、或者在原有的信息中增加扩展节点来处理用户需求。另外,Openfire本身也支持插件开发,开发者可以根据需求,以插件的形式添加所需要的功能,例如好友列表、群成员列表等,而不需要去修改核心的源代码。

(2)并发能力

  Openfire的通信处理基于Apache MINA框架实现,单机可支持上万的并发,同时也支持集群。

(3)安全性:

  XMPP在C2S通信,和S2S通信中都使用TLS协议作为通信通道的加密方法,保证通信的安全

(3)对Web的支持:

  Openfire采用内置的jetty作web服务器,可以方便的在上面增加WEB功能。jetty服务器是随AdminConsolePlugin插件时启动,通过调用startup()方法。9090为其明文端口,9091为其加密端口。

  3、通信机制

  1、帐号体系

  (1)XMPP服务器的帐号基础,是域(Domain),例如:org.example.com,它在服务器配置时的时候设置,也是服务器能被访问到的域名或IP地址。客户端连接的时候,用这个域去寻找服务器。

  (2)JID:XMPP中,任何一个可能进行通信的实体,包括一个用户、或者一个聊天室,都需要一个JID。

  用户的JID格式为:usre@domain,如:abc@org.example.com

  聊天室的JID为:room@conference.domain, 如ABC@conference.org.example.com

  一般情况,JID后面还会附带一个资源名(resource),指代这个客户端的来源,比如:abc@org.example.com/pc-abc,表示这个JID在一台名为pc-abc的设备上登录。这是同一个帐号能够在多个设备中登录的基础。

  2、通信端口

  C-S连接的端口是5222 ,S-S连接的端口为5269,这些端口已经在IANA注册。

  3、通信机制

  当客户端连接上XMPP服务器创建会话时,首先是建立一个TCP长连接,并在这个连接上收发XML流进行协商,协商通过后,服务端与客户端,可以通过Message、Presence、IQ这三种格式进行数据交换。

  这三种数据交换格式,下面逐个做介绍:

  (1)Message:基本的消息发送,不要求得到响应,用于即时通信、群组、通知等

  结构如下:

<message from='1002@zy-fordestiny' to='1001@zy-fordestiny' xml:lang='en'>
<body>Are you OK?</body>
</message>

  其中:

  To : 消息接收方JID。

  from : 消息发送方JID

  body: 所要发送的消息。

  (2)Presence:用来表明用户的状态,当用户离线或改变自己的状态时,就会在stream的上下文中插入一个Presence元素,来表明自身的状态.

  结构如下:

<presence from='1001@zy-fordestiny' to='1002@zy-fordestiny'>
<status> Online </status>
</presence>

  (3)IQ:一种请求/响应机制,类似于Http的get请求。

  结构如下:(以客户端请求服务器绑定资源为例)

<iq type='set' id='bind_1'>
<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'/>
</iq>

  iq消息中,type是主要属性,值包括:

Get :获取当前域值。
Set :设置或替换get查询的值。
Result :说明成功的响应了先前的查询。
Error: 查询和响应中出现的错误。

  4、通信示例

  下面以一个客户端登录IM服务器的例子,说明客户端与服务的交互过程。其中C-S表示客户端往服务端发消息,S-C表示服务端往客户端发消息。

  1、初始stream

  C-S:

<stream:stream xmlns='jabber:client' to='zy-fordestiny'
xmlns:stream='http://etherx.jabber.org/streams'
version='1.0'
from='10023@zy-fordestiny'
xml:lang='en'>

  S-C:

<?xml version='1.0' encoding='UTF-8'?>
<stream:stream xmlns:stream="http://etherx.jabber.org/streams"
xmlns="jabber:client"
from="zy-fordestiny"
id="34hpvqh6zz"
xml:lang="en"
version="1.0">

  S-C:通知客户端STL认证

<stream:features>
<starttls xmlns="urn:ietf:params:xml:ns:xmpp-tls"></starttls>
<mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl">
<mechanism>PLAIN</mechanism>
<mechanism>ANONYMOUS</mechanism>
<mechanism>SCRAM-SHA-1</mechanism>
<mechanism>CRAM-MD5</mechanism>
<mechanism>DIGEST-MD5</mechanism>
<mechanism>JIVE-SHAREDSECRET</mechanism>
</mechanisms>
<compression xmlns="http://jabber.org/features/compress">
<method>zlib</method>
</compression>
<auth xmlns="http://jabber.org/features/iq-auth"/>
<register xmlns="http://jabber.org/features/iq-register"/>
</stream:features>

  2、TLS协商

  C-S:

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

  S-C:通知客户端可以进行STL协商

<proceed xmlns="urn:ietf:params:xml:ns:xmpp-tls"/>

  3、客户端和服务器尝试通过已有的TCP连接完成 TLS 握手

  4、如果 TLS 握手成功,客户端初始化一个新的流给服务器

  C-S:

<stream:stream xmlns='jabber:client' to='zy-fordestiny'
xmlns:stream='http://etherx.jabber.org/streams'
version='1.0'
from='10023@zy-fordestiny'
xml:lang='en'>

  S-C:

<?xml version='1.0' encoding='UTF-8'?>
<stream:stream xmlns:stream="http://etherx.jabber.org/streams"
xmlns="jabber:client" from="zy-fordestiny" id="34hpvqh6zz"
xml:lang="en" version="1.0">
<stream:features>
<mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl">
<mechanism>PLAIN</mechanism>
<mechanism>ANONYMOUS</mechanism>
<mechanism>SCRAM-SHA-1</mechanism>
<mechanism>CRAM-MD5</mechanism>
<mechanism>DIGEST-MD5</mechanism>
<mechanism>JIVE-SHAREDSECRET</mechanism>
</mechanisms>
<compression xmlns="http://jabber.org/features/compress">
<method>zlib</method>
</compression>
<auth xmlns="http://jabber.org/features/iq-auth"/>
<register xmlns="http://jabber.org/features/iq-register"/>
</stream:features>

  4 开始SASL握手

  C-S:客户端选择一种验证机制

<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl'
mechanism='SCRAM-SHA-1'>biwsbj0xMDAyMyxyPUpkYjNr
Vn5mLzYwYH05N0tdfmk2M3Q8Wj14cmdnIy1S</auth>

  S-C:

<challenge xmlns="urn:ietf:params:xml:ns:xmpp-sasl">
cj1KZGIza1Z+Zi82MGB9OTdLXX5pNjN0PFo9eHJnZyMtUmQ0ODQ3MGFjLWU4YjAtNG
Q3NS05ZDAzLWI4NjE3MTI0ODlhYSxzPU5aQjJ2bzljcjlqNjFINEE5L1dLMWtOMVFjVnVJVFlkLGk9NDA5Ng==
</challenge>

  C-S:

<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
Yz1iaXdzLHI9SmRiM2tWfmYvNjBgfTk3S11+aTYzdDxaPXhyZ2cjLVJkNDg0NzBh
Yy1lOGIwLTRkNzUtOWQwMy1iODYxNzEyNDg5YWEscD11QStXMFBWQnFKWnNWQjVZd2pNRlVESGFGQjQ9
</response>

  S-C:通知客户端验证成功

<success xmlns="urn:ietf:params:xml:ns:xmpp-sasl">
dj02a1l6bkFDVHRLaGNEdVlVR1BlY1FWZ283RzQ9
</success>

  5、stream

  C-S:客户端发起一个新的流

<stream:stream xmlns='jabber:client' to='zy-fordestiny'
xmlns:stream='http://etherx.jabber.org/streams'
version='1.0' from='10023@zy-fordestiny'
id='34hpvqh6zz'
xml:lang='en'>

  S-C:服务器发送一个流头信息回应客户端,并附上任何可用的特性,注意,多了session

<?xml version='1.0' encoding='UTF-8'?>
<stream:stream xmlns:stream="http://etherx.jabber.org/streams"
xmlns="jabber:client" from="zy-fordestiny" id="34hpvqh6zz"
xml:lang="en" version="1.0">
<stream:features>
<compression xmlns="http://jabber.org/features/compress">
<method>zlib</method>
</compression>
<bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"/>
<session xmlns="urn:ietf:params:xml:ns:xmpp-session">
<optional/>
</session>
<sm xmlns='urn:xmpp:sm:2'/><sm xmlns='urn:xmpp:sm:3'/>
</stream:features>

  6. 资源绑定,重要!!

  C-S:

<iq id='h1q24-3' type='set'>
<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'>
<resource>ZY-fordestiny</resource>
</bind>
</iq>

  S-C:

<iq type="result" id="h1q24-3" to="zy-fordestiny/34hpvqh6zz">
<bind xmlns="urn:ietf:params:xml:ns:xmpp-bind">
<jid>10023@zy-fordestiny/ZY-fordestiny</jid>
</bind>
</iq> 

  7、获取花名册

  C-S:

<iq id='h1q24-5' type='get'>
<query xmlns='jabber:iq:roster'></query>
</iq>

  S-C:

<iq type="result" id="h1q24-5" to="10023@zy-fordestiny/ZY-fordestiny">
<query xmlns="jabber:iq:roster"/>
</iq>

  8、发送disco#items,查询server所支持的components

  C-S:

<iq to='zy-fordestiny' id='h1q24-6' type='get'>
<query xmlns='http://jabber.org/protocol/disco#items'></query>
</iq>

  S-C:

<iq type="result" id="h1q24-6" from="zy-fordestiny" to="10023@zy-fordestiny/ZY-fordestiny">
<query xmlns="http://jabber.org/protocol/disco#items">
<item jid="pubsub.zy-fordestiny" name="Publish-Subscribe service"/>
<item jid="conference.zy-fordestiny" name="公共房间"/>
<item jid="broadcast.zy-fordestiny" name="Broadcast service"/>
<item jid="proxy.zy-fordestiny" name="Socks 5 Bytestreams Proxy"/>
</query>
</iq>  

  9、获取名片,群组

  C-S:

<iq id='h1q24-23' type='get'>
<vCard xmlns='vcard-temp'/>
</iq>

  S-C:

<iq type="result" id="h1q24-23" to="10023@zy-fordestiny/ZY-fordestiny">
<vCard xmlns="vcard-temp"/>
</iq>

  C-S:

<iq id='h1q24-24' type='get'>
<sharedgroup xmlns='http://www.jivesoftware.org/protocol/sharedgroup'>
</sharedgroup>
</iq>

  S-C:

<iq type="result" id="h1q24-24" to="10023@zy-fordestiny/ZY-fordestiny">
<sharedgroup xmlns="http://www.jivesoftware.org/protocol/sharedgroup"/>
</iq>

  10、提交在线状态

  C-S:

<presence id='h1q24-10'>
<status>在线</status>
<priority>1</priority>
<c xmlns='http://jabber.org/protocol/caps'
hash='sha-1'
node='http://www.igniterealtime.org/projects/smack'
ver='njE08O0d+gOu+3R5iJiJSheFRMw='/>
</presence>

  

  可以看到,完整的登录过程,需要经过多次的信息交换。

  关于XMPP的其他信息,可以网上查阅资源了解,这里不再赘述。

  

  后面的章节,将一步步的从Openfire的源代码入手,分析整套系统的运行机制,望对读者有帮助。


  over!

Openfire分析之一:Openfire与XMPP协议的更多相关文章

  1. 即时通信系统Openfire分析之一:Openfire与XMPP协议

     引言 目前互联网产品使用的即时通信协议有这几种:即时信息和空间协议(IMPP).空间和即时信息协议(PRIM).针对即时通讯和空间平衡扩充的进程开始协议SIP(SIMPLE)以及XMPP.PRIM与 ...

  2. 基于XMPP协议(openfire服务器)的消息推送实现

    转自:http://blog.csdn.net/nomousewch/article/details/8088277 最近好像有不少朋友关注Android客户端消息推送的实现,我在之前的项目中用到过J ...

  3. Openfire与XMPP协议

    关于xmpp协议可以参考:http://www.jabbercn.org 什么是OpenFire Openfire 采用Java开发,开源的实时协作(RTC)服务器基于XMPP(Jabber)协议. ...

  4. iOS xmpp协议实现聊天之openfire的服务端配置(一)

    今天弄这个openfire服务端的配置直接苦了一逼,只是好在最后最终配置好了.首先感谢@月光的尽头的博客给了我莫大的帮助. 切入正题,首先说一下iOS xmpp协议实现聊天openfireserver ...

  5. iOS xmpp协议实现聊天之openfire的服务端配置(二)

    本篇主要说一下怎样利用命令行来正确配置MySql. 首先打开终端: 1.为mysql起一个别名 alias mysql=/usr/local/mysql/bin/mysql 2.创建mysql的管理员 ...

  6. 即时通信系统Openfire分析之五:会话管理

    什么是会话? A拨了B的电话 电话接通 A问道:Are you OK? B回复:I have a bug! A挂了电话 这整个过程就是会话. 会话(Session)是一个客户与服务器之间的不中断的请求 ...

  7. 基于XMPP协议的aSmack源码分析

    在研究如何实现Pushing功能期间,收集了很多关于Pushing的资料,其中有一个androidnp开源项目用的人比较多,但是由于长时间没有什么人去维护,听说bug的几率挺多的,为了以后自己的产品稳 ...

  8. 即时聊天IM之三 XMPP协议客户端库的和Android端框架概述

    合肥程序员群:49313181.    合肥实名程序员群:128131462 (不愿透露姓名和信息者勿加入) Q  Q:408365330     E-Mail:egojit@qq.com smack ...

  9. 基于XMPP协议的Android即时通信系

    以前做过一个基于XMPP协议的聊天社交软件,总结了一下.发出来. 设计基于开源的XMPP即时通信协议,采用C/S体系结构,通过GPRS无线网络用TCP协议连接到服务器,以架设开源的Openfn'e服务 ...

随机推荐

  1. linux 的一些脑洞操作

    把当前文件夹的文件名用","连接成一行,或者将多行转变为一行 ls | paste -s -d "," # -s 选项将输入进行一次性粘贴 ls | xargs ...

  2. Linux基础(三)

    一.正文处理命令及tar命令 1.文件合并 cat a.txt b.txt > c.txt 2.打包 归档命令tar可以把多个文件打包成一个文件 如tar cvf test.tar a.txt ...

  3. 人工智能(AI)库TensorFlow 踩坑日记之二

    上次 踩坑日志之一 遗留的问题终于解决了,所以作者(也就是我)终于有脸出来写第二篇了. 首先还是贴上 卷积算法的示例代码地址 :https://github.com/tensorflow/models ...

  4. 代理(Proxy)和反射(Reflection)

    前面的话 ES5和ES6致力于为开发者提供JS已有却不可调用的功能.例如在ES5出现以前,JS环境中的对象包含许多不可枚举和不可写的属性,但开发者不能定义自己的不可枚举或不可写属性,于是ES5引入了O ...

  5. java核心技术面试整理

    [前方高能,是这半年BAT,京东,远景,华为,中兴以及苏研发中心被问到的Java公共问题的一个整理] ------------------------------------------------- ...

  6. Python零基础学习系列之一--初识计算机!

    1-1.计算机概念: Computer: 原指专门负责计算的人,后来演变成特指计算设备,译为"计算机" 计算机的概念: 计算机是能够根据一组指令操作数据的机器. A compute ...

  7. 52. leetcode 96. Unique Binary Search Trees

    96. Unique Binary Search Trees Given n, how many structurally unique BST's (binary search trees) tha ...

  8. Uva 679 Dropping Ballls 二叉树的编号

    这个程序常规处理起来数据量很大,I可以高达2^D-1 /* ....... */ 里面的代码块据此避免了开太大的数组 做太多的循环 #include<cstdio> #include< ...

  9. 七月SSL行业新闻回顾

    大事件一:被泄露的私钥和基于假私钥进行的撤回 上个月,我们报告说Spotify和Cisco在应用程序中捆绑了有效证书的私钥.这些证书将根据基准要求被撤销,但应用程序不是泄露私钥的唯一来源.Koen R ...

  10. python 脚本在linux环境下运行

    有两种方式:1.直接使用python xxxx.py执行.其中python可以写成python的绝对路径.使用which python进行查询.2.在文件的头部(第一行)写上#!/usr/bin/py ...