<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    IM即時通訊研究

    openfire專題研究

    BlogJava 首頁 新隨筆 聯系 聚合 管理
      2 Posts :: 0 Stories :: 12 Comments :: 0 Trackbacks
     

    openfire開發文檔
    版本:Openfire3.5.
    作者:---------- 日期:-----------

     

    一、初始工作····································2

    1、安裝jdk1.5

    2、安裝eclipse,myeclipse

    3、安裝oracle10gXE

    4、安裝openfire3.5.1源代碼

    二、環境配置····································

    1、配置java環境

    2、配置openfire運行環境

    三、代碼研究····································

    四、功能擴展····································

    五、與客戶端一起調試··························


    第一章:初始工作

    1.1安裝jdk1.5

    方法1:放在F盤的安裝程序的java開發工具文件夾里

        方法2:可從www.sun.com.cn下載jdk1.5.

    1.2安裝eclipse3.3,myeclipse6.0

        放在F盤的安裝程序的java開發工具文件夾里

    1.3安裝oracle10gXE

        放在F盤的安裝程序的java開發工具文件夾里

    1.4安裝openfire3.5.1源代碼

        源代碼的下載

    方法1:放在F盤的openfire文件夾里

    方法2:可從openfire的官方網站下載,網址在IE的收藏夾里

    ②源代碼的安裝

    將下載好的openfire源代碼解壓出來,復制到eclipseworkspace里,打開eclipse,點新建java工程,在Contents里選擇第二個,即Create project from existing source, Directory選項里點右邊的Browse按鈕,選擇eclipseworkspace里的openfire文件夾(這個文件夾的名字應該叫:openfire_src),點確定。再填入Project name,工程名字一定要和eclipseworkspace里的openfire源代碼的文件夾名字相同,如下圖所示:

    點擊完成,即成功導入openfire源代碼到eclipse中。如下圖所示:

    右擊工程,點屬性->Java Build Path ->Libraries加入所對應的測試jar包,叫test什么什么的,放在E盤里。點擊完成,即可將錯誤消除。

    第二章:環境配置

    2.1、配置java環境

        我的電腦點右鍵,選擇“屬性”。

    選擇“高級”標簽。

    進入環境變量設置:

    分別設置如下三個環境變量:
    PATH=C:"jdk1.6.0"bin
    CLASSPATH=.;%JAVA_HOME%"lib"tools.jar;%JAVA_HOME%"lib"dt.jar(注意,CLASSPATH最前面是有個“.”的,表示當前目錄)
    JAVA_HOME=C:"jdk1.6.0

    設置完成之后,我們來測試一下。開始-》運行,輸入“CMD”,回車。

    在打開的DOS命令窗口中輸入“java -version”,回車。

    如果能像上圖那樣顯示JDK的版本,說明“PATH”變量設置沒有問題,如果有問題,檢查PATH變量設置,輸入“echo %PATH%”。

    看其中是否存在“C:"jdk1.6.0"bin”。如果不存在則返回到環境變量設置中檢查。

    接下來我們編寫一個簡單的Java程序測試CLASSPATH是否設置正確。

    打開記事本,輸入下面的內容,保存至C:"java目錄下,文件名為HelloWorld.java。(注意大小寫)

    class HelloWorld{
    public static void main(String[] arg){
    System.out.println("HelloWorld");
    }
    }

    在打開的DOS命令窗口,進入C:"java,輸入“java HelloWorld.java”,回車。

    這時在C:"java目錄下多了一個“HelloWorld.class”的文件。

    在打開DOS命令窗口,輸入“java HelloWorld”,回車。

    如果程序沒錯,那么將輸出“HelloWorld”。

    恭喜,你的Java環境配置成功了。

    2.2、配置openfire運行環境

        點擊運行按鈕旁邊的小的黑色三角,點擊Open Run Dialog…

    出現如下窗口,雙擊Java Application,Name框里的名字改成:openfire_src3.5.1,點擊Main class右邊的Search按鈕,

     

     

    出現如下窗口:

    在第一個文本框里輸入server,在第二個框里選擇ServerStarter-org.jivesoftware.openfire.starter,點OK

     

    點擊eclipse菜單Window->Show View->Ant,如圖:

     

    ant窗口里右擊選擇Add Buildfiles…,如下圖所示:

     

    出現如下窗口:選擇:openfire_src->build->build.xml,點擊OK按鈕。

     

    雙擊在ant窗口里生成的菜單,即開始部署項目。

     

    察看console里顯示的信息:如果顯示BUILD SUCCESSFUL就表示項目部署成功。如圖:

     

     

    第三章:代碼研究

    Openfiresocket網絡連接包括:

    <!--[if !supportLists]-->1.       <!--[endif]-->服務器和服務器之間的連接(監聽在端口5269

    <!--[if !supportLists]-->2.       <!--[endif]-->外部組件和服務器之間的連接(監聽在端口5275

    <!--[if !supportLists]-->3.       <!--[endif]-->多元(complex)連接(監聽在端口5269

    <!--[if !supportLists]-->4.       <!--[endif]-->客戶端和服務器的連接(監聽在端口5222

    <!--[if !supportLists]-->5.       <!--[endif]-->和客戶端通過TLS/SSL3.0和服務器的連接。(監聽在端口5223

    這些連接都是通過ConnectionManager接口實現管理的,程序中對ConnectionManager接口的實現類是ConnectionManagerImpl,它是作為一個模塊(Module)類加載到服務器中的。

    下面分析的是客戶端和服務器的連接。

     

    ConnectionManagerImpl中是通過調用startClientListeners方法來初始化和開始端口監聽的。

    Mina框架<!--[endif]-->startClientListeners方法使用的是ApacheMina框架來實現網絡連接的,Mina框架的模式如下:

    IoFilter

           IoFilterMINA的功能擴展提供了接口。它攔截所有的IO事件進行事件的預處理和后處理。它與Servlet中的filter機制十分相似。多個IoFilter存放在IoFilterChain

           IoFilter能夠實現以下功能:

                  數據轉換

                  事件日志

                  性能檢測

           Openfire中主要用filter這種機制來進行數據轉換。

    Protocol Codec Factory

           Protocol Codec Factory提供了方便的Protocol支持,通過它的EncoderDecoder,可以方便的擴展并支持各種基于Socket的網絡協議,比如HTTP服務器、FTP服務器、Telnet服務器等等。

           要實現自己的編碼/解碼器(codec)只需要實現interface: ProtocolCodecFactory即可,在Openfire中實現ProtocolCodecFactory的類為XMPPCodecFactory

    IoHandler:

        MINA中,所有的業務邏輯都有實現了IoHandlerclass完成    ,當事件發生時,將觸發IoHandler中的方法:

               sessionCreated

    sessionOpened

    sessionClosed

    sessionIdle

    exceptionCaught

    messageReceived

    messageSent

           Openfire中客戶端和服務器連接的IoHandler實現類是ClientConnectionHandler,它是從ConnectionHandler中繼承來的。

    startClientListeners方法首先為Mian框架設置線程池,再將一個由XMPPCodecFactory作為Protocol Codec FactoryFilter放入到FilterChain中,然后綁定到端口5222,并將ClientConnectionHandler作為IoHandler對數據進行處理。完成這些步驟后Openfire就在5222等待客戶端的連接。

    客戶端連接的處理過程:

     

    當有客戶端進行連接時根據Mina框架的模式首先調用的是sessionOpened方法。

           sessionOpened首先為此新連接構造了一個parserXMLLightWeightParser),這個parser是專門給XMPPDecoder(是XMPPCodecFactory的解碼器類)使用的,再創建一個OpenfireConnection類實例connection和一個StanzaHandler的實例。最后將以上的parser, connectionStanzaHandler的實例存放在Minasession中,以便以后使用。

           當有數據發送過來時,Mina框架會調用messageReceived方法

           messageReceived首先從Minasession中得到在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模塊進行處理。

     

     

     

     

     

     

     

     

     

     

     

     

     

     

    第四章:功能擴展

    4.1修改源代碼

        用戶的創建。由于源代碼中用戶信息不能滿足要求,需要擴展。服務器端創建用戶比較簡單,主要是客戶端的創建比較復雜,主要有4個步驟,客戶端發送創建用戶的請求(get請求),請求創建的用戶字段,服務器端接收到之后進行過濾,然后返回信息(result),信息中只包含合法的用戶屬性,客戶端收到之后,再將合法的用戶字段發送給服務器(set請求),服務器再根據收到的用戶字段創建用戶,即寫入數據庫。

    用戶的查詢。過程類似上面用戶的創建。

    4.2插件開發

    Openfire 服務器端是支持插件開發的,開發過程可能會涉及到數據庫的操作,本篇文章專注于Openfire 插件的部分,對服務器端涉及到數據庫的開發只做簡單介紹。

    Openfire
    是一個用Java 實現的XMPP 服務器,客戶端可以通過IQ 的方式與其進行通信(其實就是XML),客戶端和服務器之間的通信是依靠底層Smack 庫提供的各種功能來完成的。其實利用插件方式來擴展Openfire 服務器端主要有兩種擴展方式,一種是對服務器控制臺頁面進行擴展(不是本文的主要內容),其實就是遵循Openfire 頁面的布局方式,進行相應的頁面擴展和功能擴展;另一種是對通信功能進行擴展。本文主要針對后者進行具體的描述

    本篇文章的結構如下:

    1
    、創建plugin.xml(這是整個插件最關鍵的文檔)
    2
    、創建服務器插件實例(實現Plugin 接口的一個類還有一批IQHandler
    3
    、打包插件(Openfire 插件也有自己的打包方式)和部署插件

    好滴,實刀實槍的來動手做吧

    1
    、創建plugin.xml

    初次開發Openfire Spark 插件的時候,很容易把二者搞混,千萬記得,這里是Openfire plugin.xml 不是第二篇文章說的那個啦!

    <?xml version="1.0" encoding="UTF-8"?>
    <plugin>
        <!-- Main plugin class 
    這里是最重要滴-->
        <class>com.im.server.plugin.GroupTreePlugin</class>

        <!-- Plugin meta-data -->
        <name>GroupTreePlugin</name>
        <description>This is the group plugin.</description>
        <author>Phoenix</author>

        <version>1.0</version>
        <date>14/03/2008</date>
        <url>http://localhost:9001/openfire/plugins.jsp</url>
        <minServerVersion>3.4.1</minServerVersion>
        <licenseType>gpl</licenseType>

        <!-- Admin console entries -->
        <adminconsole>
            <!-- More on this below -->
        </adminconsole>
    </plugin>

    最重要的那一行我已經標記出來啦,就是你這個插件的初始化和垃圾清理類,例子中是在com.im.server.plugin 包中的GroupTreePlugin 類,下文會對這個類進行詳細描述。其余的都是描述信息,只要你提供了正確的描述信息,一般都不會出錯。建議初次開發者,在寫完plugin.xml 文件后,寫一個簡單的Plugin 實例,并打印出一些信息,如果重新啟動Openfire 信息成功顯示,恭喜你,你已經邁出一大步了!

    2
    、實現Plugin 類和IQHandler

    Plugin
    類主要起到的作用是初始化和釋放資源,在初始化的過程中,最重要的的注冊一批IQHandlerIQHander 的作用有點類似于Spark 中的IQProvider,其實就是解析XML 文件之后,生成一些有用的實例,以供處理。下面分別給出一個Plugin 類的實例和IQProvider 的實例

    GroupTreePlugin


    /**
     *
    服務器端插件類
     *
     * @author Phoenix
     *
     * Mar 14, 2008 11:03:11 AM
     *
     * version 0.1
     */
    public class GroupTreePlugin implements Plugin
    {
        private XMPPServer server;

        /*
         * (non-Javadoc)
         *
         * @see org.jivesoftware.openfire.container.Plugin#destroyPlugin()
         */
        public void destroyPlugin()
        {

        }

        /*
         * (non-Javadoc)
         *
         * @see org.jivesoftware.openfire.container.Plugin#initializePlugin(org.jivesoftware.openfire.container.PluginManager,
         *      java.io.File)
         */
        public void initializePlugin(PluginManager manager, File pluginDirectory)
        {
            PluginLog.trace("
    注冊群組樹IQ處理器");
            server = XMPPServer.getInstance();
           
            server.getIQRouter().addHandler(new GroupTreeIQHander()); //1
            server.getIQRouter().addHandler(new UserInfoIQHandler());
            server.getIQRouter().addHandler(new DelUserIQHandler());
            server.getIQRouter().addHandler(new CreateUserIQHandler());
            server.getIQRouter().addHandler(new AddGroupUserIQHandler());
            server.getIQRouter().addHandler(new SetRoleIQHandler());

        }

    }

    上例所示,在初始化中先找到IQRouter,然后通過IQRouter 注冊一批IQHandler,這些IQHander 會自動監聽相應命名空間的IQ,然后進行處理;由于這個Plugin 不需要做資源釋放的工作,所以在destroyPlugin() 方法中沒有任何內容。具體的IQHander 類如下

    GroupTreeIQHander

    /**
     *
    處理客戶端發來的IQ,并回送結果IQ
     *
     * @author Phoenix
     *
     * Mar 14, 2008 4:55:33 PM
     *
     * version 0.1
     */
    public class GroupTreeIQHander extends IQHandler
    {

        private static final String MODULE_NAME = "group tree handler";

        private static final String NAME_SPACE = "com:im:group";

        private IQHandlerInfo info;

        public GroupTreeIQHander()
        {
            super(MODULE_NAME);
            info = new IQHandlerInfo("gruops", NAME_SPACE);
        }

        /*
         * (non-Javadoc)
         *
         * @see org.jivesoftware.openfire.handler.IQHandler#getInfo()
         */
        @Override
        public IQHandlerInfo getInfo()
        {
            return info;
        }

        /*
         * (non-Javadoc)
         *
         * @see org.jivesoftware.openfire.handler.IQHandler#handleIQ(org.xmpp.packet.IQ)
         */
        @Override
        public IQ handleIQ(IQ packet) throws UnauthorizedException
        {
            IQ reply = IQ.createResultIQ(packet);
            Element groups = packet.getChildElement();//1
           
            if (!IQ.Type.get.equals(packet.getType()))
            {
                System.out.println("
    非法的請求類型");
                reply.setChildElement(groups.createCopy());
                reply.setError(PacketError.Condition.bad_request);
                return reply;
            }
           
            String userName = StringUtils.substringBefore(packet.getFrom().toString(),"@");

            GroupManager.getInstance().initElement(groups,userName);
           
            reply.setChildElement(groups.createCopy());//2

            System.out.println("
    返回的最終XML" + reply.toXML());

            return reply;
        }

    }

    可以看到主要有兩個方法,一個是getInfo() 這個方法的目的是提供要解析的命名空間,在本例中,這個IQHandler 對每個命名空間為"com:im:group" 的實例進行處理;還有一個最重要的方法:handleIQ() 該方法對包含指定命名空間的XML 進行解析,然后返回一個解析好的IQ。其實我認為,這個IQHandler IQ 的關系就是Controller Model 的關系(如果你了解MVC 的話,那么你一定知道我再說什么),只不過這里并沒有指定什么View,你完全可以把IQ 當成Model 類進行理解。在這里,我用了GroupManager 進行了XML 的處理,因為我返回的IQ 內容中要從數據庫讀取所有群組信息,所以轉交給GroupManager 進行處理,你完全可以在這個方法中進行具體的XML 處理,在這里,解析和創建新的XML 主要用到的是JDOM(如果你對Java 解析XML 有所了解,那真的太好了!)。程序//1 處主要是獲取創建返回的IQ,并獲取原來IQ 的子元素(用于創建我們返回的IQ);程序//2 處很關鍵,如果你不調用createCopy 方法,程序會出錯(程序會死鎖還是什么,忘記咧,不好以西)。

    這就是程序的主體部分,我在這里有一個建議,能不用Openfire 原始的程序函數,就不要用它們。我的提取數據庫方式都是自己寫的Bean,這樣有利于你自己對程序的掌控,其實更有利于快速開發(這世道不是啥都講究敏捷么,哇哈哈)

    3
    、打包插件

    打包依然遵循二次打包的原則(如果你不了解啥叫要二次打包,請看上一篇)
    這是我的ant 文件,由于Eclipse 幫我做了build 等很多工作,實際我的ant 工作就是在打包,并放入插件目錄下的plugin 文件夾下

    <?xml version="1.0" encoding="UTF-8"?>
    <project name="IM" default="release" basedir=".">

        <property name="openfire.path"
            value="E:/workspace/europa/openfire_src/target/openfire" />
        <property name="classes.dir" value="classes" />
        <property name="lib.dir" value="lib" />

        <target name="jar">
            <jar jarfile="${lib.dir}/grouptreeplugin.jar" basedir="${classes.dir}" >
                <fileset dir=".">
                    <include name="*.jar"/>
                </fileset>
            </jar>
            <jar jarfile="${openfire.path}/plugins/groupTreePlugin.jar">
                <fileset dir=".">
                    <include name="lib/*.jar" />
                    <include name="plugin.xml" />
                    <include name="logo_small.gif" />
                    <include name="logo_large.gif" />
                    <include name="readme.html" />
                    <include name="changelog.html" />
                    <include name="build.xml" />
                </fileset>
            </jar>

        </target>

        <target name="release" depends="jar">
        </target>

    </project>

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

    第五章:與客戶端一起調試

    5.1debug模式啟動服務器,根據客戶端的需要在相應位置設置端點,分析數據。

    posted on 2009-02-11 10:07 gissing 閱讀(46706) 評論(7)  編輯  收藏

    Feedback

    # re: openfire開發指南[未登錄] 2009-05-25 23:16 alex
    你很強,,我很崇拜你  回復  更多評論
      

    # re: openfire開發指南 2009-06-29 21:36 錢奕
    研究小組:
    您們好!
    我現在安裝配置openfire時出現一些障礙,想請高手支招。

    我是一個完全不懂程序的人,呵呵,openfire+spark程序在本地電腦上調試一切正常,可是不知道為什么遠程服務器的時候鏈接數據庫總是失敗。
    提示:The Openfire database schema does not appear to be installed. Follow the installation guide to fix this error.
    我用的是MSSQL,localhost/數據庫名稱,用戶名和密碼都正確的,但總是過不去這一關,不知是何原因。急急急…………

    我的QQ:70734260(輸贏) 幫幫忙,呵呵  回復  更多評論
      

    # re: openfire開發指南[未登錄] 2009-09-03 14:02 knight
    你真的很強 我崇拜!我的qq是24568468希望以后能多交流  回復  更多評論
      

    # re: openfire開發指南 2009-09-08 17:07 yzheng
    很不錯,我也在研究openfire,想將其優化一下,希望你能寫一些關于優化openfire的文章,給我一些指點,謝謝了!
    郵箱:zhengyu.willian@gmail.com
    QQ:119079436
    我會一直關注的!  回復  更多評論
      

    # re: openfire開發指南[未登錄] 2009-09-14 09:28 gissing
    我們小組得研究群號碼是:28588322,歡迎進群討論
      回復  更多評論
      

    # re: openfire開發指南[未登錄] 2011-10-21 17:52 vincent
    群滿了。
    請問openfire的網頁是怎么實現的,能不能把基本原理講一下?  回復  更多評論
      

    # re: openfire開發指南 2014-07-31 17:54 ACE
    mark  回復  更多評論
      


    只有注冊用戶登錄后才能發表評論。


    網站導航:
     
    主站蜘蛛池模板: 曰批免费视频播放在线看片二| 亚洲狠狠婷婷综合久久| 亚洲日本乱码卡2卡3卡新区| 亚洲最大中文字幕无码网站| 曰批免费视频播放免费| 永久免费av无码入口国语片| 91精品免费在线观看| 国产猛烈高潮尖叫视频免费| 亚洲综合网站色欲色欲| 亚洲电影在线免费观看| 在线精品自拍亚洲第一区| 东方aⅴ免费观看久久av| 很黄很黄的网站免费的| 午夜亚洲av永久无码精品| 午夜影视日本亚洲欧洲精品一区| 2020天堂在线亚洲精品专区| 午夜肉伦伦影院久久精品免费看国产一区二区三区| 国产特黄一级一片免费| 一本岛高清v不卡免费一三区| 日韩精品亚洲专区在线观看| 亚洲伦另类中文字幕| 亚洲AV无码国产一区二区三区| 成人国产精品免费视频| 国产1024精品视频专区免费| 亚洲国产日韩成人综合天堂| 亚洲精品国产手机| 九九免费观看全部免费视频| 国产92成人精品视频免费| 亚洲第一页日韩专区| 亚洲人成在线免费观看| 国产精品九九久久免费视频| 免费在线看v网址| 亚洲另类激情综合偷自拍图| 国产成人精品日本亚洲11| 两个人www免费高清视频| 无码人妻精品一二三区免费| 亚洲国产无套无码av电影| 亚洲欧美成人综合久久久| 日本免费一区二区三区| 亚洲福利在线播放| 中文字幕亚洲男人的天堂网络|