openfire 分析

在Openfire中主要用filter这种机制来进行数据转换。

Protocol Codec Factory:

       Protocol Codec Factory提供了方便的Protocol支持,通过它的Encoder和Decoder,可以方便的扩展并支持各种基于Socket的网络协议,比如HTTP服务器、FTP服务器、Telnet服务器等等。

       要实现自己的编码/解码器(codec)只需要实现interface:ProtocolCodecFactory即可,在Openfire中实现ProtocolCodecFactory的类为XMPPCodecFactory。

IoHandler:

    MINA中,所有的业务逻辑都有实现了IoHandler的class完成    ,当事件发生时,将触发IoHandler中的方法:

           sessionCreated

sessionOpened

sessionClosed

sessionIdle

exceptionCaught

messageReceived

messageSent

       在Openfire中客户端和服务器连接的IoHandler实现类是ClientConnectionHandler,它是从ConnectionHandler中继承来的。

startClientListeners方法首先为Mian框架设置线程池,再将一个由XMPPCodecFactory作为Protocol Codec Factory的Filter放入到FilterChain中,然后绑定到端口5222,并将ClientConnectionHandler作为IoHandler对数据进行处理。完成这些步骤后Openfire就在5222等待客户端的连接。

客户端连接的处理过程:

 

当有客户端进行连接时根据Mina框架的模式首先调用的是sessionOpened方法。

       sessionOpened首先为此新连接构造了一个parser(XMLLightWeightParser),这个parser是专门给XMPPDecoder(是XMPPCodecFactory的解码器类)使用的,再创建一个Openfire的Connection类实例connection和一个StanzaHandler的实例。最后将以上的parser, connection和StanzaHandler的实例存放在Mina的session中,以便以后使用。

       当有数据发送过来时,Mina框架会调用messageReceived方法

       messageReceived首先从Mina的session中得到在sessionOpened方法中创建的StanzaHandler实例handler,然后从parsers中得到一个parser(如果parsers中没有可以创建一个新的实例)(注意这个parser和在sessionOpened方法中创建的parser不同,这个parser是用来处理Stanza的,而在sessionOpened方法中创建的parser是在filter中用来解码的,一句话说就是在sessionOpened方法中创建的parser是更低一层的parser)。最后将xml数据包交给StanzaHander的实例hander进行处理。

       StanzaHander的实例hander处理xml数据包的过程

       StanzaHander首先判断xml数据包的类型,.如果数据包以“<stream:stream”打头那么说明客户端刚刚连接,需要初始化通信(符合XMPP协议)Openfire首先为此客户端建立一个与客户端JID相关的ClientSession,而后与客户端交互协商例如是否使用SSL,是否使用压缩等问题。当协商完成之后进入正常通信阶段,则可以将xml数据包交给这个用户的ClientSession进行派送(deliever),经过派送数据包可以发送给PacketRouteImpl模块进行处理。

 

命名规则

Openfire中常见的类名后缀命名包括Starter、Plugin、Listener、Dispatcher、Handler、Manager、Provider,通常情况下,这些命名类包括如下意义:

XXStarter

系统启动类,如

org.jivesoftware.openfire.starter.ServerStarter,调用其start()方法可启动系统应用。

XXListener

业务的最终处理类。

 

XXDispatcher

调度类,其中有很多关键方法,如addListener(),以组合的方式,为类内定义的静态Set<XXListener>实例添加XXListener对象。以便调用dispatchEvent(Stringproperty, EventType eventType, Map<String, Object> params)方法遍历处理Set集中的XXListener对象(通过调用XXListener对象的各实际方法完成实际业务)。

 

XXPlugin

实现Plugin接口的插件类,需实现initializePlugin(PluginManager manager, File pluginDirectory)方法和destroyPlugin()方法。在其初始化方法中调用Dispatcher实现类的addListener()方法如

PropertyEventDispatcher.addListener(this)。

 

XXProvider

   实现面向接口编程方式的接口类,通过反射机制创建具体实现类的对象,反射类名配置在ofproperty表对应的记录propvalue属性中。若没有相关配置,则调用默认实现类,默认实现类类名命名规则为DefaultXXProvider。

 

XXHandler

   实际处理类,以ConnectionHandler为例,在

org.jivesoftware.openfire.spi. ConnectionManagerImpl类的startClientSSLListeners(StringlocalIPAddress)方法中,有这样一段代码:

sslSocketAcceptor.bind(new InetSocketAddress(bindInterface,port),newClientConnectionHandler(serverName));其中bind方法的第二个参数是新创建的一个ClientConnectionHandler的实例,而它就是ConnectionHandler的一个子类。

 

系统启动流程

   系统启动时调用ServerStarter类中的start()方法,通过反射加载org.jivesoftware.openfire.XMPPServer类文件,创建实例时调用其构造函数,在其构造函数中调用其start()方法实际启动服务应用程序。Start()方法中首先调用verifyDataSource()方法验证并确保数据库可以访问,然后会调用loadModules();initModules();startModules();方法来对Module接口的实现类的各子类进行操作,依次完成模块的加载、初始化和启动操作。loadModules()方法中会调用loadModule(String module)方法通过反射加载各模块类,参数字符串module为对应的模块核心处理类的类名,如AdHocCommandHandler。现以AdHocCommandHandler为例对接下来的处理流程进行说明。通过loadModule创建AdHocCommandHandler类实例时调用其构造函数,在构造函数中初始化了其私有AdHocCommandManager对象。在initModules()时调用AdHocCommandHandler实例的initialize(XMPPServer server)方法对其私有属性对象进行初始化。然后调用start()方法,调用addDefaultCommands方法添加命令并启动命令(通过调用startCommand(AdHocCommand command)方法实现)。

网络处理

消息监听服务

SSL等监听服务的调度在ConnectionManagerImpl类中实现。ConnectionManagerImpl.createClientSSLListeners()方法启动SSL监听

 

消息封装

信息处理采用XML节的方式传递信息,消息封装通常采用IQ、Message、Presence。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值