Android--XMPP协议学习笔记

XMPP协议学习笔记一


  • 即时通讯技术简介

    即时通讯技术(IM)支持用户在线实时交谈。如果要发送一条信息,用户需要打开一个小窗口,以便让用户及其朋友在其中输入信息并让交谈双方都看到交谈的内容。大多数常用的即时通讯发送程序都会提供各种各样的功能:

  1. 即时通讯 - 在用户和在线朋友之间来回发送信息
  2. 聊天 - 创建用户与朋友或工友的自定义聊天室
  3. 网页链接 - 共享用户喜爱的网址
  4. 支持图片 - 浏览朋友计算机中的图片
  5. 支持声音 - 给朋友播放音乐
  6. 支持文件传输 - 直接将文件发送给朋友,以便于共享
  7. 交谈 - 使用 Internet,而不是电话,与朋友们进行真正的交谈
  8. 影音串流内容 - 实时或准实时的股市行情或新闻

  有许多的IM系统,如 AOL IM、Yahoo IM、 MSN IM还有我们熟悉的QQ,它们最大的区别在于各自通讯协议的实现,所以即时通讯技术的核心在于它的传输协议,协议用来说明信息在网络上如何传输,如果有了 统一的传输协议,那么应当可以实现各个IM之间的直接通讯,为了创建即时通讯的统一标准,人们经过了多次尝试:IETF 的对话初始协议(SIP)和即时通讯对话初始协议和表示扩展协议(SIMPLE)、应用交换协议(APEX)、显示和即时通讯协议(PRIM)及基于 XML 且开放的可扩展通讯和表示协议(XMPP)协议(常称为 Jabber 协议)。人们多次努力,试图统一各大主要 IM 供应商的标准(AOL、Yahoo 及 Microsoft),但无一成功,且每一种 IM 仍然继续使用自己所拥有的协议。

 

  • 几种IM协议标准简介


    IMPP 主要定义必要的协议和数据格式,用来构建一个具有空间接收、发布能力的即时信息系统。到目前为止,这个组织已经出版了三个草案RFC,但主要的有两个:一 个是针对站点空间和即时通讯模型的(RFC 2778);另一个是针对即时通讯/空间协议需求条件的(RFC2779)。RFC2778是一个资料性质的草案,定义了所有presence和IM服务 的原理。RFC2779定义了IMPP的最小需求条件。另外,这个草案还就presence服务定义了一些条款,如运行的命令、信息的格式,以及 presence服务器如何把presence的状态变化通知给客户。 

    SIMPLE是目前为止制定的较为完善的一个。SIMPLE和 XMPP两个协议,都符合RFC2778和RFC2779 。SIMPLE计划利用SIP来发送presence信息。SIP是IETF中为终端制定的协议。SIP一般考虑用在建立语音通话中,一旦连接以后,依* 如实时协议(RTP)来进行实际上的语音发送。但SIP不仅仅能被用在语音中,也可以用于视频。SIMPLE被定义为建立一个IM进程的方法。 SIMPLE在2002年夏季得到额外的信任,目前,微软和IBM都致力于在它们的即时通讯系统中实现这个协议。 

    SIMPLE小组致力于进程模式的操作,这将提升运行效率,使基于SIP的机制能够进行会议和三方电话交谈控制,也考虑到能和未来提供的许多新特性实现兼 容并提升表现能力。有了进程模式,SIMPLE使用SIP来建立一次进程,再利用SDP(进程描述协议)来实际传输IM数据。 

    XMPP是一种基于XML的协议,它继承了在XML环境中灵活的发展性。这表明XMPP是可扩展的。可以通过发送扩展的信息来处理用户的需求,以及在 XMPP的顶端建立如内容发布系统和基于地址的服务等应用程序。而且,XMPP包含了针对服务器端的软件协议,使之能与另一个进行通话,这使得开发者更容 易建立客户应用程序或给一个配好系统添加功能。 

    XMPP目前在免费源代码开放Jabber IM系统中被广泛采用。2002年,这个产品有超过5万的下载量。XMPP拥有成千的Jabber开发者,以及大约数万台配置的服务器和超过百万的终端用户。

  • XMPP概述 

    XMPP: The Extensible Messaging and Presence Protocol   

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

    简介:可扩展通讯和表示协议 (XMPP) 可用于服务类实时通讯、表示和需求 - 响应服务中的 XML 数据元流式传输。XMPP 以 Jabber 协议为基础,而 Jabber 是即时通讯中常用的开放式协议。XMPP is the IETF's formalization of the base XML streaming protocols for instant messaging and presence developed within the Jabber open-source community in 1999   

    XMPP(可扩展消息处理现场协议)是基于可扩展标记语言(XML)的协议,它用于即时消息(IM)以及在线现场探测。它在促进服务器之间的准即时操作。这个协议可能最终允许因特网用户向因特网上的其他任何人发送即时消息,即使其操作系统和浏览器不同。   

    XMPP的前身是Jabber,一个开源形式组织产生的网络即时通信协议。XMPP目前被IETF国际标准组织完成了标准化工作。标准化的核心结果分为两部分;   

    核心的XML流传输协议   

    基于XML FreeEIM流传输的即时通讯扩展应用   

    XMPP的核心XML流传输协议的定义使得XMPP能够在一个比以往网络通信协议更规范的平台上。借助于XML易于解析和阅读的特性,使得XMPP的协议能够非常漂亮。   

    XMPP的即时通讯扩展应用部分是根据IETF在这之前对即时通讯的一个抽象定义的,与其他业已得到广泛使用的即时通讯协议,诸如AIM,QQ等有功能完整,完善等先进性。   

    XMPP的扩展协议Jingle使得其支持语音和视频。    

    XMPP的官方文档时RFC 3920.

  • XMPP的基本结构

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

  • XMPP通过TCP传的是什么

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

  • XMPP的相关文档

      推荐一个包含XMPP相关资料的百度空间:http://hi.baidu.com/jabber/home

      XMPP官网:http://xmpp.org/

      Jabber官网,包含许多XMPP的实现:http://www.jabber.org/

============================================================

XMPP协议学习笔记二


  • IM的实现原理

    在我最初学习编程的时候,曾经用JAVA实现了一个最简单版的IM通讯,即通过Socket建立两台电脑之间的连接,然后发送IO流来进行即时通讯,我们 现在所使用的IM软件尽管看上去非常复杂,但是基本的原理和以上的差不多,无非是采用服务器<>客户端的架构,通过登陆到服务器来获取个人资 料和好友,然后聊天时直接通过IP和好友进行即时通讯。

  • XMPP协议的网络架构

    XMPP是一个典型的C/S架构,而不是像大多数即时通讯软件一样,使用P2P客户端到客户端的架构,也就是说在大多数情况下,当两个客户端进行通讯时, 他们的消息都是通过服务器传递的(也有例外,例如在两个客户端传输文件时).采用这种架构,主要是为了简化客户端,将大多数工作放在服务器端进行,这样, 客户端的工作就比较简单,而且,当增加功能时,多数是在服务器端进行.XMPP服务的框架结构如下图所示.XMPP中定义了三个角色,XMPP客户 端,XMPP服务器、网关.通信能够在这三者的任意两个之间双向发生.服务器同时承担了客户端信息记录、连接管理和信息的路由功能.网关承担着与异构即时 通信系统的互联互通,异构系统可以包括SMS(短信)、MSN、ICQ等.基本的网络形式是单客户端通过TCP/IP连接到单服务器,然后在之上传输 XML,工作原理是:

  1. 节点连接到服务器;
  2. 服务器利用本地目录系统中的证书对其认证;
  3. 节点指定目标地址,让服务器告知目标状态;
  4. 服务器查找、连接并进行相互认证;
  5. 节点之间进行交互。

    XMPP协议的传输是通过XML文件来传输的,并且不是类似于QQ的点对点通讯,而是客户端到服务器再到客户端的方式来实现,以上过程的一个简单的XMPP通讯流程可以如下:

  1.  首先,由客户端连接到服务器,客户端通过IO流发送一段XML文件,在文件中包含了自身的用户名和密码。
  2.  服务器端接收到客户端的XML文件,从中获取用户名和密码进行验证,如果验证成功,服务器会发送一个XML文件给客户端表明已经登录成功。
  3.  登陆成功后,客户端可以通过发送一个获取好友名单的XML文件,服务器会将当前用户的好友以XML文件传到客户端。
  4.  客户端选择一个好友,向其发送信息(其实是向服务器发送,服务器收到后会转发给对应的好友),好友收到。

     通过以上的流程,一此基本的通讯得以达成。

Spark架构

    (上图为XMPP的一个实现Openfire+Smack+Spark的实现)

  • XMPP协议的一些概念

     通过以上简介,我们了解了XMPP协议的基本流程,下面来了解一个XML中一些基本的概念。

  • XMPP地址

    一个实体在XMPP网络结构中被称为一个节点,它有唯一的标示符jabber identifier(JID),即实体地址,用来表示一个用户,但是也可以表示其他内容,例如一个聊天室.一个有效的JID包括一系列元素:(1)域名 (domain identifier);(2)节点(node identifier);(3)源(resource identifier).它的格式是node@domain/resource,node@domain,类似电子邮件的地址格式.domain用来表示 接点不同的设备或位置,这个是可选的,例如a在Server1上注册了一个用户,用户名为doom,那么a的JID就是doom@serverl,在发送 消息时,指明doom@serverl就可以了,resource可以不用指定,但a在登录到这个Server时,fl的JID可能是 doom@serverl、exodus(如果a用Exodus软件登录),也可能是doom@serverl/psi(如果a用psi软件登录).资源 只用来识别属于用户的位置或设备等,一个用户可以同时以多种资源与同一个XMPP服务器连接。

  • XMPP的XML流

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

   举个例子看看所谓的XML流是什么样子的? 

客户端:<?xml version='1.0'?> 

   <stream:stream 

       to='example.com' 

       xmlns='jabber:client' 

       xmlns:stream='http://etherx.jabber.org/streams' 

       version='1.0'> 

服务器:<?xml version='1.0'?> 

   <stream:stream 

       from='example.com' 

       id='someid' 

       xmlns='jabber:client' 

       xmlns:stream='http://etherx.jabber.org/streams' 

       version='1.0'> 

...其他通信... 

客户端:<message from='juliet@example.com' 

              to='romeo@example.net' 

              xml:lang='en'> 

客户端: <body>Art thou not Romeo, and a Montague?</body> 

客户端:</message> 

服务器:<message from='romeo@example.net' 

              to='juliet@example.com' 

              xml:lang='en'> 

服务器:<body>Neither, fair saint, if either thee dislike.</body> 

服务器:</message> 

客户端:</stream:stream> 

服务器:</stream:stream> 

    以文档的观点来看,客户端或服务器发送的所有XML文本连缀在一起,从<stream>到</stream>构成了一个完整的 XML文档。其中的stream标签就是所谓的XML Stream。在<stream>与</stream>中间的那些<message>...< /message>这样的XML元素就是所谓的XML Stanza(XML节)。XMPP核心协议通信的基本模式就是先建立一个stream,然后协商一堆安全之类的东西,中间通信过程就是客户端发送XML Stanza,一个接一个的。服务器根据客户端发送的信息以及程序的逻辑,发送XML Stanza给客户端。但是这个过程并不是一问一答的,任何时候都有可能从一个方发信给另外一方。通信的最后阶段是</stream>关闭 流,关闭TCP/IP连接。

  • XML节


    XML节通过XML流来发送,XMPP定义了三种顶级XML节

  1. <iq />
  2. <message />
  3. <presence />


    XMPP给这三种节定义了五种通用属性

  1. to
  2. from
  3. id
  4. type
  5. xml:lang


    to属性指定接收节的JID。

    from属性指定发送者的JID。

    id属性是可选的。并且,在接收应用(通常是一个服务器)中是唯一的。注意:流ID可能是严格安全的,并且因此必须是即不能预测也不能重复的

    type属性指定目的或消息上下文,出席或IQ节的详细信息。iq节的type属性有:Error,Get,Result,Set; presence节的type属性有:Available,Subscribe,Subscribed,Unsubscribe,        Unsubscribed,Unavailable,Probe,Error,Invisible; message节的type属性有:Chat,Error,GroupChat,Headline,Normal

    xml:lang属性值指定任意可读XML字符数据的缺省语言

    <message />节定义了消息语义,<message />节可被看作“推”机制,一个实体推信息给其它实体,与EMAIL系统中发生的通信类似。所有消息节应该拥有‘to’属性,指定有意的消息接收 者;根据接收到那样的一个节,服务器应该路由或传送它到有意的接收者。

    <presence />节定义了出席语义,<presence />节可被看作基本广播或“出版-订阅”机制,多实体收到他们已订阅(在这种情况下,网络可利用信息)实体的信息。总的来说,出版实体应该发送一个 不带‘to’属性的出席节,在这种情况下,与此实体相连的服务器应该广播给所有订阅实体。然而,一个出版实体也可能发送一个带有‘to’属性的出席节,此 种情况下,服务器应该路由或传送节到有意的接收者。

    <iq />节定义了请求语义,<iq />节可被看作一个请求-响应机制,与[HTTP]在某些方面相似。IQ语义让一个实体向其它实体请求或接收其它实体的响应成为可能。请求与响应的 数据内容由IQ无素的直接子元素的命名空间声明定义,并且,交互由请求实体通过使用‘id’属性来跟踪。因此,IQ交互遵从结构化数据交换的一个通用模 式,此交换例如得到/结果或设置/结果(虽然如果合适的话,对一个请求的响应可能会以错误返回)。

===============================================================

XMPP协议学习笔记三(Openfire服务器端搭建开发环境)

    在了解了XMPP的基本结构和一些概念之后,我们暂时告别枯燥的理论学习,来动手搭建一下Openfire+Spark的开发环境,实际感受一下搭建整套IM通讯系统的过程。
  • 开发环境:windows XP sp3,Eclipse3.6.1,jdk1.6.0_24,Ant1.7
  • 首先从官网上下载最新版本的openfire源码

官网

  • 第二步,在Eclipse中创建名为openfire的java项目

项目

  • 将openfire源码中openfire_src下的所有文件复制到此项目中,效果如下

复制

  • 项目有错误是因为jar包没有加进来,右键点击项目选择Properties,添加build/lib下所有的jar包

jar

  • 为了方便编辑,我们要把各个插件的源代码抽出来,在Properties文件夹中选择Source,Add Folders,把src/java和plugins下面的所有插件前边打上勾。

打钩

  • 效果如下

效果1

  • 下一步,复制src/i18n/openfire_i18n_en.properties和src/resources/jar/admin-sidebar.xml两个文件,到项目下的bin目录。

效果2

  • 然后,我们用ant来编译整个项目,选择项目下的build/build.xml文件,运行,若是出现BUILD SUCCESSFUL则编译成功,不行就多来几遍。
  • 下面建立项目builder,选择src/java/org/jivesoftware/openfire/starter /ServerStarter.java,右击run as>run configurations,在出现的对话框中选择java application>Arguments,在VM Arguments中输入-DopenfireHome="${workspace_loc:openfire}/target/openfire"  ,注意这里的openfire相当于我们的项目名,大小写要注意。再选择Classpth>User Entries,然后点击Advanced>Add Folders,选取项目下的resource文件和src/i18n文件添加进来

加入文件

加入文件2

设置VM参数

  • 至此,项目建构完毕,运行ServerStarter.java,会出现以下提示。

最终

======================================================

XMPP协议学习笔记四(Openfire服务器启动过程)


    在上篇文章中我们成功部署了openfire的源码,这一篇我们来初步了解一下openfire的项目结构。

  • 概述

    Openfire最主要的功能是实现XMPP服务器,简单来说,openfire为我们提供一个固定的地址,我们只需要向openfire服务器发送标准 的XMPP信息(即XML文件流),那么openfire服务器应当给予我们回应,这里的openfire服务器也可以看做一个容器,我们在聊天时,需要 在这个服务器上注册一个会话,在会话存在的时间,我们可以实现即时聊天的一些常用功能,比如建立自己的组,添加好友,聊天,以及传送文件等等,同 时,openfire服务器也需要实现自己的管理界面,这样openfire服务器也扮演一个web容器的角色。

 

    XMPP协议是基于TCP/IP协议进行传输的,在openfire中,应用了apache的mina框架作为NIO框架,简单的来说,openfire 服务器用mina框架建立一个简单的服务器,可以接收和发送基本的IO流,然后在此基础上把接收到的IO流解析为XML文件,然后在根据XMPP协议对 XML文件进行操作。

  • Openfire启动过程

    系统启动时调用org.jivesoftware.openfire.starter.ServerStarter类中的start()方法,加载 org.jivesoftware.openfire.XMPPServer类,并调用这个类的start()方法进行一系列的初始化操作,下面是 XMPPServer的Start()方法

  1. public void start() {  
  2.         try {  
  3.             initialize();  
  4.   
  5.             startDate = new Date();  
  6.             // Store server info  
  7.             xmppServerInfo = new XMPPServerInfoImpl(name, host, version, startDate, getConnectionManager());  
  8.   
  9.             // Create PluginManager now (but don't start it) so that modules may use it  
  10.             File pluginDir = new File(openfireHome, "plugins");  
  11.             pluginManager = new PluginManager(pluginDir);  
  12.   
  13.             // If the server has already been setup then we can start all the server's modules  
  14.             if (!setupMode) {  
  15.                 //这个方法是验证数据库连接是否正确  
  16.                 verifyDataSource();  
  17.                 //加载所有模块  
  18.                 // First load all the modules so that modules may access other modules while  
  19.                 // being initialized  
  20.                 loadModules();  
  21.                 // Initize all the modules  
  22.                 initModules();  
  23.                 // Start all the modules  
  24.                 startModules();  
  25.             }  
  26.             // Initialize statistics  
  27.             ServerTrafficCounter.initStatistics();  
  28.   
  29.             // Load plugins (when in setup mode only the admin console will be loaded)  
  30.             pluginManager.start();  
  31.   
  32.             // Log that the server has been started  
  33.             String startupBanner = LocaleUtils.getLocalizedString("short.title") + " " + version.getVersionString() +  
  34.                     " [" + JiveGlobals.formatDateTime(new Date()) + "]";  
  35.             Log.info(startupBanner);  
  36.             System.out.println(startupBanner);  
  37.   
  38.             started = true;  
  39.               
  40.             // Notify server listeners that the server has been started  
  41.             for (XMPPServerListener listener : listeners) {  
  42.                 listener.serverStarted();  
  43.             }  
  44.         }  
  45.         catch (Exception e) {  
  46.             e.printStackTrace();  
  47.             Log.error(e.getMessage(), e);  
  48.             System.out.println(LocaleUtils.getLocalizedString("startup.error"));  
  49.             shutdownServer();  
  50.         }  
  51.     }  
    个人觉得,openfire服务器的启动过程相当清晰,所有的模块都实现了Module接口,然后在启动时统一调用所有模块的initial()方法和start()方法,简单明了又便于扩展,在今后自己的项目中值得加以运用。

=============================================================

XMPP协议学习笔记五(Openfire消息处理流程)


     XMPP协议作为一个IM,其核心在于消息的传递,在Openfire服务器对XMPP的实现中,消息被封装为Packet对象,因此Openfire服 务器的核心代码是对客户端Packet对象的监听和处理流程,我们今天就来研究一下Openfire的消息包接受处理流程。

     

  • 首先,Openfire服务器需要启动一个基于TCP/IP的监听服务,用以接收客户端传过来的XML流文件。这个过程在XMPPServer类 的start()方法中进行,这个监听服务是以loadModule(ConnectionManagerImpl.class.getName())来 加载,调用ConnectionManagerImpl类的createClientListeners()方法
  1. private void createClientListeners() {  
  2.     // Start clients plain socket unless it's been disabled.  
  3.     if (isClientListenerEnabled()) {  
  4.         // Create SocketAcceptor with correct number of processors  
  5.         socketAcceptor = buildSocketAcceptor();  
  6.         // Customize Executor that will be used by processors to process incoming stanzas  
  7.         ExecutorThreadModel threadModel = ExecutorThreadModel.getInstance("client");  
  8.         int eventThreads = JiveGlobals.getIntProperty("xmpp.client.processing.threads"16);  
  9.         ThreadPoolExecutor eventExecutor = (ThreadPoolExecutor)threadModel.getExecutor();  
  10.         eventExecutor.setCorePoolSize(eventThreads + 1);  
  11.         eventExecutor.setMaximumPoolSize(eventThreads + 1);  
  12.         eventExecutor.setKeepAliveTime(60, TimeUnit.SECONDS);  
  13.   
  14.         socketAcceptor.getDefaultConfig().setThreadModel(threadModel);  
  15.         // Add the XMPP codec filter  
  16.         socketAcceptor.getFilterChain().addFirst("xmpp"new ProtocolCodecFilter(new XMPPCodecFactory()));  
  17.         // Kill sessions whose outgoing queues keep growing and fail to send traffic  
  18.         socketAcceptor.getFilterChain().addAfter("xmpp""outCap"new StalledSessionsFilter());  
  19.     }  
  20. }  
  • 其中的socketAcceptor是在buildSocektAcceptor()方法中定义的,它是作为一个服务端的接收器,是mina框架 为我们封装好的一个socketserver,在上面这个方法中,我们为socketAcceptor添加了一个过滤 器,XMPPCodeFactory,这个类将过滤xmpp相关请求,加以处理,我们再看同一个类的另外一个方法 startClientListener()
  1. private void startClientListeners(String localIPAddress) {  
  2.    // Start clients plain socket unless it's been disabled.  
  3.    if (isClientListenerEnabled()) {  
  4.        int port = getClientListenerPort();  
  5.        try {  
  6.            // Listen on a specific network interface if it has been set.  
  7.            String interfaceName = JiveGlobals.getXMLProperty("network.interface");  
  8.            InetAddress bindInterface = null;  
  9.            if (interfaceName != null) {  
  10.                if (interfaceName.trim().length() > 0) {  
  11.                    bindInterface = InetAddress.getByName(interfaceName);  
  12.                }  
  13.            }  
  14.            // Start accepting connections  
  15.            socketAcceptor  
  16.                    .bind(new InetSocketAddress(bindInterface, port), new ClientConnectionHandler(serverName));  
  17.   
  18.            ports.add(new ServerPort(port, serverName, localIPAddress, falsenull, ServerPort.Type.client));  
  19.   
  20.            List<String> params = new ArrayList<String>();  
  21.            params.add(Integer.toString(port));  
  22.            Log.info(LocaleUtils.getLocalizedString("startup.plain", params));  
  23.        }  
  24.        catch (Exception e) {  
  25.            System.err.println("Error starting XMPP listener on port " + port + ": " +  
  26.                    e.getMessage());  
  27.            Log.error(LocaleUtils.getLocalizedString("admin.error.socket-setup"), e);  
  28.        }  
  29.    }  
  • 其中的socketAcceptor.bind()方法启动了监听服务器,来监听所有发送到服务器5222端口的数据,并用 ClientConnetionHandler类来处理,ClinetConnectionHandler继承于ConnectionHandler类, 后者实现了mina的IoHandlerAdaptor接口,其中的messageReceived()方法是关键。
  1. public void messageReceived(IoSession session, Object message) throws Exception {  
  2. // Get the stanza handler for this session  
  3. StanzaHandler handler = (StanzaHandler) session.getAttribute(HANDLER);  
  4. // Get the parser to use to process stanza. For optimization there is going  
  5. // to be a parser for each running thread. Each Filter will be executed  
  6. // by the Executor placed as the first Filter. So we can have a parser associated  
  7. // to each Thread  
  8. int hashCode = Thread.currentThread().hashCode();  
  9. XMPPPacketReader parser = parsers.get(hashCode);  
  10. if (parser == null) {  
  11.     parser = new XMPPPacketReader();  
  12.     parser.setXPPFactory(factory);  
  13.     parsers.put(hashCode, parser);  
  14. }  
  15. // Update counter of read btyes  
  16. updateReadBytesCounter(session);  
  17. //System.out.println("RCVD: " + message);  
  18. // Let the stanza handler process the received stanza  
  19. try {  
  20.     handler.process((String) message, parser);  
  21. catch (Exception e) {  
  22.     Log.error("Closing connection due to error while processing message: " + message, e);  
  23.     Connection connection = (Connection) session.getAttribute(CONNECTION);  
  24.     connection.close();  
  25. }  
可以看到收到的信息交由StanzaHandler的process方法中进行XML解析并封装为packet对象,然后再进行下一步的处理,至此,从客户端到服务器端的packet传递结束。


(###)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值