(转)OpenFire源码学习之一:XMPP基础知识

转:http://blog.csdn.net/huwenfeng_2011/article/details/43412919

前面两张主要讲基础部分。XMPP与Mina有部分抄写于互联网的其他大事

XMPP概述

XMPP: The Extensible Messaging and Presence Protocol

中文全称:可扩展通讯和表示协议

Xmpp是一种类似于http的通讯传输协议,它是一个“包装”/“解包”的过程。

XMPP适合新项目的优势:

l  无需投入成本制定协议

l  易于扩展

l  可迅速完成原型

l  适合各种容量系统,从100用户在线的系统到100万以上在线用户。

l  可扩展至 Web/Flash IM, Mobile IM 等各种场合,基本都有开源实现或Library。

l  发展比较成熟稳定

基本网络结构

XMPP中定义了三个角色,客户端,服务器,网关。通信能够在这三者的任意两个之间双向发生。服务器同时承担了客户端信息记录,连接管理和信息的路由功能。网关承担着与异构即时通信系统的互联互通,异构系统可以包括SMS(短信),MSN,ICQ等。基本的网络形式是单客户端通过TCP/IP连接到单服务器,然后在之上传输XML。

功能

传输的是与即时通讯相关的指令。在以前这些命令要么用2进制的形式发送(比如QQ),要么用纯文本指令加空格加参数加换行符的方式发送(比如MSN)。而XMPP传输的即时通讯指令的逻辑与以往相仿,只是协议的形式变成了XML格式的纯文本。这不但使得解析容易了,人也容易阅读了,方便了开发和查错。而XMPP的核心部分就是一个在网络上分片段发送XML的流协议。这个流协议是XMPP的即时通讯指令的传递基础,也是一个非常重要的可以被进一步利用的网络基础协议。所以可以说,XMPP用TCP传的是XML流。

XML流和XML节

XML流的定义:

一个XML流是一个容器,包含了两个实体之间通过网络交换的XML元素。一个XML流是由一个XML打开标签 <stream> (包含适当的属性和名字空间声明)开始的,流的结尾则是一个XML关闭</stream>标签 。在流的整个生命周期,初始化它的实体可以通过流发送大量的XML元素,用于流的握手(例如 TLS 握手 或 SASL 握手)或XML节(在这里指符合缺省名字空间的元素,包括<message/>,<presence/>,或 <iq/> 元素)。“初始的流”由初始化实体(通常是一个客户端或服务器)和接收实体(通常是一个服务器)握手,从接收实体来看,它就是那个初始实体的"会话"。初始化流允许从初始化实体到接收实体的单向通信;为了使接收实体能够和初始实体交换信息,接收实体必须发起一个反向的握手(应答流)。

XML节的定义:

一个XML节是一个实体通过 XML 流向另一个实体发送的结构化信息中的一个离散的语义单位。一个XML节直接存在于根元素<stream/>的下一级,这样可以说是很好的匹配 了[XML]。任何XML节都是从一个XML流的下一级的某个打开标签(如 <presence>)开始,到相应的关闭标签(如 </presence>)。一个XML节可以包含子元素(相关的属性、元素、和 XML 字符数据等) 以表达完整的信息。在这里定义的XML节仅限于<message/>,<presence/>,和 <iq/> 元素。

stream 属性


 


初始化方发给接收方


接收方发给初始化方


说明


to


接收方的主机名


忽略


该属性仅出现在初始化实体发给接收实体的 XML 流的头当中,并且它的值必须是接收实体所在的主机名。若 ‘to‘ 属性出现在应答流中,则初始化实体忽略它。


from


忽略


发送方的主机名


该属性仅出现在接收实体发给初始化实体的 XML 流的头当中,并且它的值必须是为当前初始化实体授权的接收实体所在的主机名。


id


忽略


会话键值


该属性仅用于接收实体发送给初始化实体 XML流的头。这个属性是一个由接收实体创建的具有唯一性的ID,一个初始实体和接收实体之间的会话ID,并且它在接收方的应用程序中必须是唯一的。注意:这个流 ID 必须是足够安全的,所以它必须是不可预知的和不可重复的。它不应该在有 ‘id‘属性出现在初始实体发送给接收实体的 XML流的头中;无论如何,如果‘id‘属性出现在初始化流中,接收实体应该忽略它。


xml:lang


缺省语言


缺省语言


它包含在初始化实体发给接收实体的 XML流的头中,以指定在流中传输的可读XML字符所使用的缺省语言。如果这个属性出现了,接收实体应该记住它的值,作为初始化流和应答流的缺省属性;如果这个属性没有出现,接收实体应该用一个可配置的缺省值用于双方的流,这个属性值必须在应答流的头中传达。对于所有初始化流中传输的节,如果初始实体没有提供‘xml:lang‘属性,接收实体应该应用缺省值;如果初始实体提供了‘xml:lang‘属性,接收实体不能修改或删除它。‘xml:lang‘属性的值必须是一个 nmtoken并且必须遵守RFC3066规定的格式。


version


支持XMPP 1.0


支持XMPP 1.0

示例:

<?xml version=‘1.0‘?>

<stream:stream

from=‘[email protected]‘

to=‘im.example.com‘

version=‘1.0‘

xml:lang=‘en‘

xmlns=‘jabber:client‘

xmlns:stream=‘http://etherx.jabber.org/streams‘>

基本节点

<presence>节点

presence节点用来控制和表示实体的在线状态,可以展示从离线到在线甚至于离开,不能打扰等复杂状态,另外,还能被用来建立和结束在线状态的订阅。

<presence>
       <show>away</show> <!--离线-->
      <status>atthe ball</status> <!--标签用于显示额外信息-->
</presence>

其中show的取值范围如下:
away:  离线
char:   交谈中
dnd:    希望不被打扰
xa:     离开一段时间

Online: 在线

<presence>
       <status>touring thecountryside</status>
      <priority>10</priority>
</presence>

在这个节中,出现了一个<priority>标签,表示现在连接的优先度。每个连接可以设置从-128到127的优先读,默认是设置为0.用户可以在这个标签里修改相应的优先度。如果有相应的设置的话,用户送往纯JID的将会送 到优先度最高的那个连接,如果设置值为负数的话,则表示送往纯JID的消息将永远不会送达该连接。

<Message>节点

message节点用于用户之间传递消息。这消息可以是单纯的聊天信息,也可以某种格式化的信息。 message节点信息是传递之后就被忘记的。当消息被送出之后,发送者是不管这个消息是否已经送出或者什么时候被接收到。通过扩展协议,可以改变这样一种状况。

下面我们看一些例子: 
<messagefrom="[email protected]"  to="[email protected]"  type="chat">
      <body>Hello!</body>
</message>

<message from="[email protected]"  to="[email protected]"  type="groupchat">
       <body>welcome</body>
</message>

其中<type>标签取值类型:

Chat:           单点聊天

Error:          错误信息  
groupchat:    多人聊天信息
headline:      通常用在自动服务中,不需要回应。

<body>          标签里面是具体的消息内容。

<iq>节点

iq节点主要是用于Info/Query模式的消息请求,他和Http协议比较相似。可以发出get以及set请求,就如同http中的GET以及POST。iq节点需要有回应,有get,set两种请求以及result,error两种回应。

<iq  from="[email protected]"  type="get"  id="roster1">
             <queryxmlns="jabber:iq:roster"/>
       </iq>

其中type属性取值:

Get:       获取当前域值

Set:       设置替换get查询的值

Result:   说明成功相应了先前的查询

Error:    查询或相应时候出现了错误

拓展协议

时间: 2024-12-29 07:02:51

(转)OpenFire源码学习之一:XMPP基础知识的相关文章

dubbo源码学习一:基础知识及使用的相关技术

Dubbo是Alibaba开源的分布式服务框架,它最大的特点是按照分层的方式来架构,使用这种方式可以使各个层之间解耦合(或者最大限度地松耦合),我们可以非常容易地通过Dubbo来构建分布式服务,并根据自己实际业务应用场景来选择合适的集群容错模式,这个对于很多应用都是迫切希望的,只需要通过简单的配置就能够实现分布式服务调用,也就是说服务提供方(Provider)发布的服务可以天然就是集群服务. Dubbo的产生背景.最初的需求.架构设计 等可以详细看官方的文档:http://dubbo.apach

OpenFire源码学习之十八:IOS离线推送

IOS离线推送 场景: 如果您有IOS端的APP,在会话聊天的时候,用户登陆了但可能会退出了界面.这时候其他终端给目标端发送消息时候,消息可以发送到IOS的推送服务器.用过QQ的都知道,你会有哦一条消息在您的主屏上展示.这个就是利用了IOS的推送服务器呢.那么openfire只需要判断用户不在线的时候将消息推送给IOS端. 苹果服务器的消息推送都需要手机的唯一标志,也就是唯一的终端设备号.那么IOS端在登陆的时候需要将该手机的设备号传递给OF服务器.这个传递很简单,您可以自定义发送IQ消息.也可

OpenFire源码学习之二十三:关于消息的优化处理

消息处理 之前有说过,openfire的消息处理策略本人并不是很喜欢.先看下openfire上脱机消息策略. 个人认为消息关于会话的消息,用户的存储量应该无限大.服务器不应该被消息吃撑了.所谓聊天通讯,这一关很重要. Openfire的消息是什么流程呢. 1.当用户登陆连接的时候.握手.认证.绑定资源.获取花名册.获取离线消息. 2.服务端会查找关系型数据库.经本人测试离线消息在数据库表中达到100万条以上的时候,查询速度非常慢,甚至会导致openfire奔溃. ..... 那么openfire

(转)OpenFire源码学习之十:连接管理(上)

转:http://blog.csdn.net/huwenfeng_2011/article/details/43415827 关于连接管理分为上下两部分 连接管理 在大并发环境下,连接资源 需要随着用户并发访问量的增加而增加,所以可伸缩的连接资源就是支持大访问量的关键技术.openfire系统通过增加独立部署的连接管理器程序提高并发的能力,连接管理的前端是一台负载均衡设备,它负责把用户访问分配到指定连接管理器,多台连接管理器在访问服务器.使用连接管理器后,服务器的连接池是提供给连接管理器连 接,

(转)OpenFire源码学习之六:用户注册

转:http://blog.csdn.net/huwenfeng_2011/article/details/43413509 用户注册 注册流程: 1.客户端进行握手给服务端发送连接消息: [html] view plain copy <stream:stream to="192.168.2.104" xmlns="jabber:client" xmlns:stream="http://etherx.jabber.org/streams" 

OpenFire源码学习之二十七:Smack源码解析

Smack Smack是一个用于和XMPP服务器通信的类库,由此可以实现即时通讯和聊天.Android中开发通讯APP也可以使用这个包.关于smack的中文开发文档,目前网上也有很多. 下面本,将从源码中分析smack的几个案例. 连接 关于smack的Connection是连接XMPP服务器的默认实现.他有两个构造函数,一个是XMPPConecttion(String) 接收服务器地址名的参数.这个是默认的比较常用的构造方法. l 查找一个DNS的SRC,首先需要找到它精确的服务器地址和端口默

OpenFire源码学习之二十九:集群

集群 Openfire的给集群提供了多种方案.一种是基于Hazelcast插件,还有基于Oracle的coherence插件. Linux集群配置 一.修改配置文件 /etc/hosts文件 openfire1 192.168.2.104 openfire2192.168.2.240 每台主机都需要配置 二.添加jar包 将coherence.jar.coherence-work.jar.tangosol.jar添加到lib目录 将clustering.jar放到plugins下面 Hazelc

OpenFire源码学习之三:在Eclipse中构建源码

源码搭建 下载地址: 地址:http://www.igniterealtime.org/downloads/source.jsp 环境准备 第1步:  在官网上在下最新源码,这里是3.8.1.解压后得到如下图所示: 第2 步: 在IDE工具上新建一个java普通工程命名openfire 第3步: 将解压后的openfire_src目录的下的所有文件源码复制到此项目下,例图所示 这里稍等片刻后,看到如下效果图: 上图中在工程上出现了错误信息报告,不用着急.原因是刚导入的项目还有些jar包没有加进来

OpenFire源码学习之四:openfire的启动流程

openfire启动 ServerStarter 启动流程图: 启动的总入口在ServerStarter的main方法中.通过上图首先它会先加载它所需要的jar文件.最后通过java反射机制将XMPPServer加入当前线程. Thread.currentThread().setContextClassLoader(loader); Class containerClass = loader.loadClass( "org.jivesoftware.openfire.XMPPServer&quo

OpenFire源码学习之十九:在openfire中使用redis插件(上)

Redis插件 介绍 Redis是目前比较流行的NO-SQL,基于K,V的数据库系统.关于它的相关操作信息,本人这里就不做重复了,相关资料可以看这个网站http://www.redis.io/(官网).http://www.redis.cn/(中文站). 这里本人想说的是,拿Redis做openfire的缓存数据库.能够大大的提高openfire连接的吞吐量.Openfire自身在本地使用Map.Cache的方式缓存了Group.roster.MUC等信息.但是当系统用户过大的时候,需要缓存的数