天天看點

使用遠端共享對象實作多人實時線上聊天 轉

FMS開發中,經常會使用共享對象來同步使用者和存儲資料。對于實作廣播文字資訊實作聊天的支援非常強大,還可以跟蹤使用者的時時動作,在開發Flash多人線上遊戲中的應用也非常廣闊。

在使用FMS開發共享對象時需要注意,隻有使用Flash Media Interactive Server或Flash Media Development Server這兩個版本時才能夠建立和使用遠端共享對象,來實作多用戶端的應用程式之間共享資料。如果是使用的Flash Media Streaming Server版FMS是不能建立遠端共享對象的,隻能建立本地共享對象,類似于傳統Web開發中的Cookie。

使用共享對象(SharedObject)來開發時時文字聊天其實是很簡單的,SharedObject可以跟蹤和廣播消息,連接配接到SharedObject中的其中任何一個用戶端改變了SharedObject中的資料,SharedObject就會将最新的資料廣播到連接配接到它的所有用戶端。從某種角度可以了解為遠端的SharedObject是一個同步很多使用者的一個網絡中心。下圖為官方釋出的SharedObject廣播消息圖:

使用遠端共享對象實作多人實時線上聊天 轉

本文是通過實作一個簡單的文字聊天來介紹FMS中的遠端共享對象的使用,首先在FMS中建立好應用程式名,既在FMS的安裝目錄下的applications下建立一檔案夾,來作為共享對象應用程式使用,如下圖所示:

使用遠端共享對象實作多人實時線上聊天 轉

如上圖,SharedObjectApp就是為實作聊天建立的一個FMS應用檔案夾,其下的sharedobjects/_definse_為成功建立遠端對象後自動生成的目錄。如果你所建立的為永久性的遠端共享對象,則在該目錄下還将會有一個以.fso為擴充名的遠端共享對象檔案。

要建立遠端共享對象,首先需要連接配接到FMS應用,然後通過SharedObject.getRemote()方法來完成遠端共享對象的建立,通過給遠端共享對象添加同步事件監聽,遠端共享對象裡的資料一但發生改變就會自動觸發該事件,來實作同步資料。

以下為引用的内容:

private function onClick():void

{

    nc = new NetConnection();

    nc.connect("rtmp://192.168.1.101/SharedObjectApp");

    nc.addEventListener(NetStatusEvent.NET_STATUS,onNetStatusHandler);

}

private function onNetStatusHandler(evt:NetStatusEvent):void

{

    this.panChat.title+="("+evt.info.code+")";

    if(evt.info.code=="NetConnection.Connect.Success")

    {

        //建立一個遠端共享對象

        //參數:遠端共享對象的名稱 | 連接配接到的應用程式的URI | 遠端共享對象是否為永久遠端對象

        so = SharedObject.getRemote("RemotingSO",nc.uri,true); //将生成SO.fso

        //遠端對象(SharedObject)同步事件的監聽

        so.addEventListener(SyncEvent.SYNC,onSyncHandler);

        //遠端共享對象連接配接到伺服器

        so.connect(nc);

    }

}

上面代碼塊實作了連接配接到FMS應用,成功連接配接後便建立遠端共享對象(RemotingSO),同時還為遠端共享對象添加了同步事件監聽,通過onSyncHandler方法來處理事件。

在繼續實作聊天功能前,我們需要編寫一個通用方法,該方法提供将一個數組裡的資料轉移到另一個數組,如下代碼塊:

以下為引用的内容:

private function convertArrayCollection(arrNew:ArrayCollection,arrOld:ArrayCollection):void

{

     arrNew.removeAll();

     for(var i:int=0;i<arrOld.length ;i++)

     {

          arrNew.addItemAt(arrOld.getItemAt(i),i);

     }

}

下面我們通過發送消息的流程開始,首先是發送消息,通過自定義Message類來封裝消息内容:

以下為引用的内容:

1 package flex.VO

 2 {

 3     public class Message

 4     {

 5         public var NickName:String;  //使用者呢稱

 6         public var Context:String;    //消息内容

 7         

 8         public function Message()

 9         {

10         }

11     }

12 }

在發送消息的時候,通過此Message類來封裝發送消息的資料,然後将其釋出到FMS中的遠端共享對象,更新遠端共享對象中的資料。

以下為引用的内容:

private function onSend():void

{

    var tempCollection:ArrayCollection = new ArrayCollection();

    if(so.data.msgCollection != null)

    {

        convertArrayCollection(tempCollection,so.data.msgCollection as ArrayCollection);

    }

    var msg:Message = new Message();

    msg.NickName = this.txtUser.text;

    msg.Context = this.txtMessage.text;

    tempCollection.addItem(msg);

    //更新遠端共享對象中的屬性值

    so.setProperty("msgCollection",tempCollection);

    this.txtMessage.text="";

}

實作了發送消息(将消息添加到遠端共享對象并更新遠端共享對象的屬性值),如果有多個用戶端連接配接到該遠端共享對象,這時就回觸發遠端共享對象的同步事件,通過同步事件處理方法就可以将遠端共享對象中的資料同步到用戶端。如下代碼塊:

以下為引用的内容:

private function onSyncHandler(evt:SyncEvent):void

{

    if(so.data.msgCollection!=null)

    {

        var tempCollection:ArrayCollection = new ArrayCollection();

        convertArrayCollection(tempCollection,so.data.msgCollection as ArrayCollection);

        this.msgText.text="";

        for(var index:int=0;index<tempCollection.length;index++)

        {

            var message:Object = tempCollection.getItemAt(index);

            var displayMessage:String = message.NickName+"說:"+message.Context;

            this.msgText.text += displayMessage + "\n";

        }

    }

}

如上便完成了整個文字聊天的功能開發,主要應用到的技術點就是通過遠端共享對象來同步使用者資料。下面為完整的Flex端代碼:

以下為引用的内容:

<?xml version="1.0" encoding="utf-8"?>

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" fontSize="12">

    <mx:Script>

        <![CDATA[

            import mx.controls.Alert;

            import mx.collections.ArrayCollection;

            import flex.VO.Message;

            private var nc:NetConnection;

            private var so:SharedObject;

            private function onClick():void

            {

                nc = new NetConnection();

                nc.connect("rtmp://192.168.1.101/SharedObjectApp");

                nc.addEventListener(NetStatusEvent.NET_STATUS,onNetStatusHandler);

            }

            private function onNetStatusHandler(evt:NetStatusEvent):void

            {

                this.panChat.title+="("+evt.info.code+")";

                if(evt.info.code=="NetConnection.Connect.Success")

                {

                    //建立一個遠端共享對象

                    //參數:遠端共享對象的名稱 | 連接配接到的應用程式的URI | 遠端共享對象是否為永久遠端對象

                    so = SharedObject.getRemote("RemotingSO",nc.uri,true); //将生成SO.fso

                    //遠端對象(SharedObject)同步事件的監聽

                    so.addEventListener(SyncEvent.SYNC,onSyncHandler);

                    //遠端共享對象連接配接到伺服器

                    so.connect(nc);

                }

            }

            private function onSyncHandler(evt:SyncEvent):void

            {

                if(so.data.msgCollection!=null)

                {

                    var tempCollection:ArrayCollection = new ArrayCollection();

                    convertArrayCollection(tempCollection,so.data.msgCollection as ArrayCollection);

                    this.msgText.text="";

                    for(var index:int=0;index<tempCollection.length;index++)

                    {

                        var message:Object = tempCollection.getItemAt(index);

                        var displayMessage:String = message.NickName+"說:"+message.Context;

                        this.msgText.text += displayMessage + "\n";

                    }

                }

            }

            private function onSend():void

            {

                var tempCollection:ArrayCollection = new ArrayCollection();

                if(so.data.msgCollection != null)

                {

                    convertArrayCollection(tempCollection,so.data.msgCollection as ArrayCollection);

                }

                var msg:Message = new Message();

                msg.NickName = this.txtUser.text;

                msg.Context = this.txtMessage.text;

                tempCollection.addItem(msg);

                //更新遠端共享對象中的屬性值

                so.setProperty("msgCollection",tempCollection);

                this.txtMessage.text="";

            }

            private function convertArrayCollection(arrNew:ArrayCollection,arrOld:ArrayCollection):void

            {

                 arrNew.removeAll();

                 for(var i:int=0;i<arrOld.length ;i++)

                 {

                      arrNew.addItemAt(arrOld.getItemAt(i),i);

                 }

            }

        ]]>

    </mx:Script>

    <mx:Panel x="22" y="22" width="482" height="260" layout="absolute"  id="panChat"

        title="文字聊天">

        <mx:TextArea x="0" y="0" width="100%" height="100%" backgroundColor="#FCDADA" id="msgText"/>

        <mx:ControlBar>

            <mx:TextInput width="53" id="txtUser"/>

            <mx:Label text="說:"/>

            <mx:TextInput width="195" id="txtMessage"/>

            <mx:Button label="Send" click="onSend()"/>

            <mx:Button label="Connection" fontWeight="normal" click="onClick()"/>

        </mx:ControlBar>

    </mx:Panel>

</mx:Application>

程式運作截圖如下:

使用遠端共享對象實作多人實時線上聊天 轉

圖1----FMS狀态圖

使用遠端共享對象實作多人實時線上聊天 轉

圖2----聊天用戶端(張三)

使用遠端共享對象實作多人實時線上聊天 轉

圖3----聊天用戶端(李四)

使用遠端共享對象實作多人實時線上聊天 轉

如上圖,在FMS應用目錄下建立了一字尾為.fso的檔案,這就是永久性的遠端共享對象檔案名。在使用遠端共享的時候,根據實際需求來确定是否使用永久性的遠端共享對象,一般做聊天應用我個人建議使用臨時遠端共享對象(不生成.fso檔案),要存儲聊天記錄可以通過其他方式來儲存。

詳細大家可以檢視官方提供的文檔,在FMS的安裝目錄下就有,我的是D:\Adobe\Flash Media Server 3\documentation\flashmediaserver_AS3LR\index.html

本文示例源代碼下載下傳:http://files.cnblogs.com/beniao/Flash/FlexChat.rar

繼續閱讀