日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

FluorineFx + Flex视频聊天室案例开发----客户端

發(fā)布時(shí)間:2025/5/22 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 FluorineFx + Flex视频聊天室案例开发----客户端 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

??????上一篇《FluorineFx + Flex視頻聊天室案例開發(fā)----服務(wù)器端》詳細(xì)的介紹了如何利用FluorineFx開發(fā)一個(gè)及時(shí)通信的視頻聊天室服務(wù)器處理程序,并通過Web網(wǎng)站來宿主這個(gè)服務(wù)處理程序的運(yùn)行。本篇將著重介紹視頻聊天室的客戶端開發(fā),包括連接RTMP服務(wù)器、發(fā)布視頻、接收視頻、在線用戶列表、發(fā)送文本消息以及全服務(wù)器小喇叭功能點(diǎn)。

??????上述這些功能點(diǎn)在我以前寫的文章里已經(jīng)出現(xiàn)了N多次了,所以這里我不想過多的在次對(duì)他們進(jìn)行解說,詳細(xì)請(qǐng)查閱《Flex與.NET互操作系列文章 》,這里我將核心的幾個(gè)方法代碼貼出來簡(jiǎn)單說明。首先就是客戶實(shí)現(xiàn)用戶登錄,通過FluorineFx提供的RemotingService的接口方法進(jìn)行數(shù)據(jù)驗(yàn)證。

private?function?onLogin(event:MouseEvent):void
{
????remoteConn?
=?new?RemotingConnection("http://localhost:2020/ChatRoom.FluorineFxWeb/Gateway.aspx",ObjectEncoding.AMF3);
????myInfo?
=?new?UserInfo();
????myInfo.UserName
=this.txtUserName.text;
????myInfo.Password
=this.txtPassword.text;
????remoteConn.RemotingCall(
"ChatRoom.Services.DataService.Login",onLoginResult,onLoginFault,myInfo);
}

private?function?onLoginResult(result:UserInfo):void
{
????
if(result?!=?null)
????{
????????
this.myInfo?=?result;
????????
this.viewStack.selectedChild?=?chatView;
????????rtmpnc?
=?new?RtmpConnection("rtmp://localhost:2777/VideoChat",ObjectEncoding.AMF3,onNetStatusHandler,myInfo);
????}
????
else
????{
????????
this.lbState.text?=?"登陸失敗,用戶名或密碼錯(cuò)誤!";
????}
}

private?function?onLoginFault(event:Object):void
{
????
this.lbState.text?=?"登陸失敗,請(qǐng)重試!";
}

private?function?onClear(event:MouseEvent):void
{
????
this.txtUserName.text="";
????
this.txtPassword.text="";
????
this.lbState.text="";
????
this.txtUserName.setFocus();
}

?

??????RemotingConnection和RtmpConnection是我自己擴(kuò)展的NetConnection類,功能和NetConnection一樣,不同的是封裝后的使用相對(duì)來說比較方便點(diǎn)。首先通過RemotingService的接口進(jìn)行用戶名和密碼驗(yàn)證,通過了則創(chuàng)建一個(gè)到RTMP服務(wù)器的連接RtmpConnection(等同于NetConnection)。

private?function?onNetStatusHandler(event:NetStatusEvent):void
{
????trace(
event.info.code);
????
switch(event.info.code)
????{
????????
case?"NetConnection.Connect.Success":onConnSuccess();break;
????????
case?"NetConnection.Connect.Failed":onConnError();break;
????}
}

private?function?onConnSuccess():void
{
????
//將自己的視頻數(shù)據(jù)發(fā)布到RTMP服務(wù)器,這里使用的是FluorineFx
????var?mic:Microphone?=?Microphone.getMicrophone();
????var?publishNs:NetStream?
=?new?NetStream(rtmpnc);
????publishNs.attachCamera(cam);
????publishNs.attachAudio(mic);
????publishNs.client?
=?this;
????publishNs.publish(myInfo.ID.toString());?
//將用戶ID作為流名進(jìn)行發(fā)布實(shí)況流
????
????userSO?
=?SharedObject.getRemote("OnLineUsers",rtmpnc.uri,false);
????userSO.addEventListener(SyncEvent.SYNC,onSyncHandler);
????userSO.client?
=?this;
????userSO.connect(rtmpnc);
????
????timer?
=?new?Timer(1000);
????timer.addEventListener(TimerEvent.TIMER,onTimerHandler);
????timer.start();
}

private?function?onConnError():void
{
????trace(
"login?error");
????writeMessage(
"<font?color=\"#FF0000\">系統(tǒng)提示:連接視頻服務(wù)器失敗</font>");
}

?

??????創(chuàng)建連接的同時(shí)指定了由那一個(gè)方法(onNetStatusHandler)來處理連接狀態(tài),通過判斷連接狀態(tài)如果連接成功則將自己的視頻數(shù)據(jù)發(fā)布到RTMP服務(wù)器(特別提醒:在發(fā)布流的時(shí)候是使用的用戶ID作為流名,在建立視頻聊天的時(shí)候需要根據(jù)這個(gè)ID才能查看到視頻),同時(shí)還連接到服務(wù)器上的遠(yuǎn)程共享對(duì)象(作用:通過異步事件處理函數(shù)實(shí)現(xiàn)在線用戶列表),最后建立了一個(gè)Timer是不斷的調(diào)用服務(wù)器方法獲取當(dāng)前系統(tǒng)時(shí)間(注意:實(shí)際開發(fā)中不建議這樣做);如果連接服務(wù)器失敗則在聊天消息顯示區(qū)輸入一條提示信息。

??????在線用戶列表使用共享對(duì)象來實(shí)現(xiàn),可以及時(shí)的處理用戶上線下線功能和實(shí)現(xiàn)客戶端數(shù)據(jù)同步更新等。下面是共享對(duì)象的異步事件處理函數(shù):

private?function?onSyncHandler(event:SyncEvent):void
{
????var?array:Array?
=?event.target.data.UserInfo?as?Array;
????
if(array?!=?null)
????{
????????userArray.removeAll();
????????
for(var?i:Number=0;?i<array.length;?i++)
????????{
????????????var?info:UserInfo?
=?array[i]?as?UserInfo;
????????????userArray.addItem(info);
????????}
????????trace(
"userArray?length:"?+?userArray.length);
????}
}

?

??????從異步事件中取出當(dāng)前最新的數(shù)據(jù),然后添加到用戶界面的顯示列表數(shù)組(userArray)里,Flex直接使用List組件顯示在線用戶列表,通過綁定userArray設(shè)置數(shù)據(jù)源,當(dāng)userArray改變后List組件的顯示也會(huì)同步更新顯示。

???????那么怎么去建立視頻聊天查看到對(duì)方的視頻呢?其實(shí)實(shí)現(xiàn)也很簡(jiǎn)單,這里還是要從用戶列表出發(fā),通過點(diǎn)擊用戶列表上的在線用戶,然后建立與該用戶的視頻連接。同時(shí)判斷是否選擇的是怎么,本案例中我沒有將自己從在線列表里屏蔽而是通過判斷當(dāng)前選擇的是否為自己,如果是自己則不進(jìn)行視頻連接,也不能發(fā)送文本聊天信息。

private?function?onUserItemHandler(event:Event):void
{
????info?
=?List(event.target).selectedItem?as?UserInfo;? //把當(dāng)前選擇的用戶信息通過變量保存下來
????
this.lbNickName.text?=?info.NickName;
????
????
if(info.UserName?==?myInfo.UserName)
????{
????????writeMessage(
"<font?color=\"#FF0000\">系統(tǒng)提示:不能和自己進(jìn)行視頻聊天</font>");
????}
????
else
????{
????????
//建立視頻流的連接
????????if(this.ns)
????????{
????????????
this.ns.close();
????????}
????????
this.ns?=?new?NetStream(this.rtmpnc);
????????ns.client?
=?this;
????????sound?
=?this.ns.soundTransform;
????????var?v1:Video?
=?new?Video();
????????v1.width?
=?320;
????????v1.height?
=?240;
????????v1.attachNetStream(ns);
????????
this.videoDisplay.addChild(v1);
????????ns.play(info.ID.toString());? //當(dāng)前選擇的用戶的ID
????}
}

?

??????OK,到這里就成功的完成了用戶登錄,建立與RTMP服務(wù)器的連接,發(fā)布視頻流,接收指定的視頻流等功能,接下來就是實(shí)現(xiàn)文字聊天的功能了。實(shí)現(xiàn)文字聊天功能是最簡(jiǎn)單的,我曾經(jīng)先后在《FMS3系列(六):使用遠(yuǎn)程共享對(duì)象(SharedObject)實(shí)現(xiàn)多人時(shí)時(shí)在線聊天(Flex | Flash) 》和《Flex與.NET互操作(十二):FluorineFx.Net的及時(shí)通信應(yīng)用(Remote Shared Objects)(三) 》這兩篇文章中都介紹到了,這里我使用的是第二篇文章里所介紹的方法(提示:該方法就是直接使用SharedObject的send()方法)來實(shí)現(xiàn)文字聊天功能。

?

private?function?onSendMessage(event:MouseEvent):void
{
????
if(info!=null)
????{
????????userSO.send(
"chatMessage",?this.txtMessage.text,?myInfo,?info);
????????
this.txtMessage.text="";
????}
????
else
????{
????????writeMessage(
"系統(tǒng)提示:請(qǐng)選擇聊天對(duì)象");
????}
}

public?function?chatMessage(message:String,?sayUser:UserInfo,?recUser:UserInfo):void
{
????
if(recUser.UserName==this.myInfo.UserName)
????{
????????message?
=?sayUser.NickName?+?"對(duì)你說:"+message;
????????writeMessage(message);
????}
????
if(sayUser.UserName==this.myInfo.UserName)
????{
????????message?
=?"我對(duì)"+recUser.NickName?+?"說:"+message;
????????writeMessage(message);
????}
}

private?function?writeMessage(message:String):void
{
????
this.txtDisMessage.htmlText?+=?message?+?"\n";
????
this.txtDisMessage.verticalScrollPosition?=?this.txtDisMessage.maxVerticalScrollPosition;
}

?

??????OK,大功告成,現(xiàn)在是集視頻和文字聊天的多人在線聊天室就實(shí)現(xiàn)了,不足的是只能一對(duì)一聊天。如果我要對(duì)大家說話怎么辦呢?于是我在本案例中設(shè)計(jì)了一個(gè)小喇叭功能,通過發(fā)送小喇叭實(shí)現(xiàn)全服務(wù)器喊話。下邊是下喇叭組件代碼:

<?xml?version="1.0"?encoding="utf-8"?>
<mx:TitleWindow?xmlns:mx="http://www.adobe.com/2006/mxml"?layout="absolute"?width="540"?height="50"?
????headerHeight
="8"?roundedBottomCorners="true"?borderColor="#000000">
????
<mx:TextInput?x="2"?y="3"?width="400"?id="txtMessage"/>
????
<mx:Button?x="466"?y="3"?label="關(guān)閉"?click="onClose(event)"/>
????
<mx:Button?x="410"?y="3"?label="發(fā)送"?
????????enabled
="{txtMessage.text.length?>?0???true?:?false}"?
????????click
="onSend(event)"/>
????
????
<mx:Script>
????????
<![CDATA[
????????????import?mx.core.Application;
????????????import?mx.events.CloseEvent;
????????????import?mx.managers.PopUpManager;
????????????
private?function?init():void
????????????{
????????????????
this.txtMessage.setFocus();
????????????}
????????????
????????????
private?function?onClose(event:MouseEvent):void
????????????{
????????????????onCloseHandler(
null);
????????????}
????????????
????????????
private?function?onCloseHandler(event:CloseEvent):void
????????????{
????????????????Application.application.speakFlag?
=?false;
????????????????PopUpManager.removePopUp(
this);
????????????}
????????????
????????????
private?function?onSend(event:MouseEvent):void
????????????{
????????????????Application.application.userSO.send(
"speakMessage",txtMessage.text,Application.application.myInfo);
????????????????
this.txtMessage.text?=?"";
????????????????onCloseHandler(
null);
????????????}
????????]]
>
????
</mx:Script>
</mx:TitleWindow>


??????同樣通過遠(yuǎn)程共享對(duì)象的send()方法實(shí)現(xiàn)發(fā)送小喇叭功能,在客戶端定義一個(gè)方法(speakMessage)來接受小喇叭發(fā)送的消息內(nèi)容,然后顯示在用戶聊天界面上。

public?var?speakFlag:Boolean?=?false;
private?function?onSpeaker(event:MouseEvent):void
{
????
if(!speakFlag)
????{
????????var?dis:Speaker?
=?new?Speaker();
????????dis.x?
=?230;
????????dis.y?
=?505;
????????PopUpManager.addPopUp(dis,
this,false);
????????speakFlag?
=?true;
????}
}
public?function?speakMessage(message:String,info:UserInfo):void
{
????message?
=?"【小喇叭】:"?+?info.NickName?+?"說:"?+?message;
????writeMessage(message);?
}

?

??????貌似這一整篇都是代碼,除了代碼我也不知道該怎么去介紹更容易說得清楚了,下面來看看上面的勞動(dòng)成功,啟動(dòng)服務(wù)器后運(yùn)行多個(gè)客戶端來聊天測(cè)試看看。????????????

????????????

????????????

????????????

?

??????現(xiàn)在還差一個(gè)重要的功能沒有實(shí)現(xiàn)了,前面提到過畫中畫功能,也就是說在和在線朋友進(jìn)行視頻聊天的同時(shí),需要將自己的視頻以小視頻窗口的方式顯示在聊天窗口,實(shí)現(xiàn)所謂的畫中畫功能,顯示自己的視頻通過初始化方法,程序啟動(dòng)后就直接顯示出自己的視頻。

private?function?init():void
{
????
//將自己的視頻顯示在畫中畫中
????cam?=?Camera.getCamera();
????
if(cam?!=?null)
????{
????????
this.myVD.attachCamera(cam);
????}
????
else
????{
????????writeMessage(
"未能找到視頻設(shè)備,請(qǐng)檢測(cè)是否正確安裝設(shè)備!");
????}
}

?

??????本文就介紹到這里,關(guān)于聊天表情的實(shí)現(xiàn)這里就不作介紹了,由于時(shí)間關(guān)系本案例里也沒有實(shí)現(xiàn)這個(gè)功能,有興趣的朋友可以下載源代碼自己去擴(kuò)展實(shí)現(xiàn)聊天表情這個(gè)功能。這里我將實(shí)現(xiàn)的原理簡(jiǎn)單說一下,通過TileList組件加載表情圖片或動(dòng)畫信息顯示出來,詳細(xì)可以參考《使用TileList+TitleWindow組件開發(fā)聊天表情功能 》,發(fā)送表情則是將圖片地址通過SharedObject的send()方法發(fā)送出去,接收消息的方法通過圖片地址,組合<img src='圖片地址' />然后顯示在聊天信息窗口中。

?

版權(quán)說明

? 本文屬原創(chuàng)文章,歡迎轉(zhuǎn)載,其版權(quán)歸作者和博客園共有。??

? 作??????者:Beniao

?文章出處:http://beniao.cnblogs.com/? 或? http://www.cnblogs.com/

?

轉(zhuǎn)載于:https://www.cnblogs.com/beniao/archive/2009/06/29/1511813.html

總結(jié)

以上是生活随笔為你收集整理的FluorineFx + Flex视频聊天室案例开发----客户端的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。