即时通信系统Openfire分析之一:Openfire与XMPP协议
引言
目前互联网产品使用的即时通信协议有这几种:即时信息和空间协议(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协议的更多相关文章
- 基于XMPP的即时通信系统的建立(二)— XMPP详解
XMPP详解 XMPP(eXtensible Messaging and Presence Protocol,可扩展消息处理和现场协议)是一种在两个地点间传递小型结构化数据的协议.在此基础上,XMPP ...
- 基于XMPP的即时通信系统的建立(一)— XMPP基础概念
相关背景 IM(Instant Messaging)正在被广泛使用,特别是公司与它们的客户互动连接方案以及互联网与Web2.0相关的应用.为了解决即时通信的标准问题,IETF(互联网工程任务组 The ...
- (转)基于即时通信和LBS技术的位置感知服务(二):XMPP协议总结以及开源解决方案
在<基于即时通信和LBS技术的位置感知服务(一):提出问题及解决方案>一文中,提到尝试使用XMPP协议来实现即时通信.本文将对XMPP协议框架以及相关的C/S架构进行介绍,协议的底层实现不 ...
- 即时通信系统Openfire分析之五:会话管理
什么是会话? A拨了B的电话 电话接通 A问道:Are you OK? B回复:I have a bug! A挂了电话 这整个过程就是会话. 会话(Session)是一个客户与服务器之间的不中断的请求 ...
- 基于XMPP的即时通信系统的建立(五)— openfire
现决定使用Openfire作为服务端,Openfire采用Java开发,基于XMPP的实时开源协作服务器.单台可支持上万并发用户. Openfire体系结构 Openfire体系由其提供的服务器端.客 ...
- Openfire分析之一:Openfire与XMPP协议
引言 上帝说,要有光,于是就有了光. 有点玄. 如果将时光回溯无数岁月,到几百万年的蛮荒时代,人类史上第一次发生信息交换,会是什么样子?是转一下脑袋,还是眨一下眼? 但不管是什么形式,于是有了信息, ...
- 即时聊天IM之二 openfire 整合现有系统用户
合肥程序员群:49313181. 合肥实名程序员群:128131462 (不愿透露姓名和信息者勿加入) Q Q:408365330 E-Mail:egojit@qq.com 综述: ...
- Openfire与XMPP协议
关于xmpp协议可以参考:http://www.jabbercn.org 什么是OpenFire Openfire 采用Java开发,开源的实时协作(RTC)服务器基于XMPP(Jabber)协议. ...
- 基于XMPP的即时通信系统的建立 — XMPP IQ详解
XMPP详解 XMPP(eXtensible Messaging and Presence Protocol,可扩展消息处理和现场协议)是一种在两个地点间传递小型结构化数据的协议.在此基础上,XMPP ...
随机推荐
- 创建hive与hbase关联的hive表与hbase表
创建hive与hbase的关联表 create external table hive_hbase(rowkey string,name string,addr string,topic string ...
- centos下安装升级python到python3.5
本文摘抄自:https://www.cnblogs.com/edward2013/p/5289056.html 请支持原版 CentOS7安装Python3.5 2. 安装Python的依赖包 ...
- Java访问控制
转自:菜鸟教程
- windows环境下nginx服务器的安装与配置
转载至:http://www.cnblogs.com/hxxy2003/archive/2012/09/20/2695254.html nginx服务器是一个高性能的HTTP和反向代理服务器,它以稳定 ...
- "助成"招聘网站视频简介
我们小组为我们的作品录制了一个一分多钟的电梯介绍视频,这是视频连接,我上传到了优酷上:http://v.youku.com/v_show/id_XMzIzMTc1ODc2NA==.html?spm=a ...
- 软工实践Beta冲刺答辩
福大软工 · 第十二次作业 - Beta答辩总结 组长本次博客作业链接 项目宣传视频链接 本组成员 1 . 队长:白晨曦 031602101 2 . 队员:蔡子阳 031602102 3 . 队员:陈 ...
- mysql hql异常
org.springframework.dao.InvalidDataAccessResourceUsageException: could not execute query; nested ex ...
- 浅谈 Sql Server 触发器
一.触发器概念 1.1.触发器特征 1.1.1.触发器是在对表进行增.删.改时,自动执行的存储过程.触发器常用于强制业务规则,它是一种高级约束,通过事件进行触发而被执行. ...
- 3dContactPointAnnotationTool开发日志(二七)
今天的主要工作是把选中物体以及复制删除物体和右边三个面板联系起来,就是通过鼠标框选住物体,右边面板的对应项的颜色也会改变,而且通过右边面板也能控制物体的选中状态,被选中的物体成cyan青色,并且包 ...
- (转)用MongoDB 实现优酷API 缓存
由于众所周知的原因, 邪恶的企业优酷于九月的某一天开始禁止第三方播放器加载视频API, 我不得不设置一个反向代理来绕过Flash 的跨域限制. 自此服务器压力激增, 导致用户体验大为劣化. 为了减少服 ...