[转载]基于stratus +flex+MySQL的简易在线随机视频聊天室的开发

[转载]基于stratus +flex+MySQL的简易在线随机视频聊天室的开发 – 疯狂的八神庵 – 博客园.

前段时间听说flashplayer已经开始支持p2p了,对这块非常感兴趣于是开始玩flex,一玩下来不可自拔。用Stratus搭建p2p环 境如此简单,双方只需要能连上Stratus服务器就能直接进行语音视频的聊天,不需要任何客户端。Adobe还真是NB,呵呵出了这么XX的东东,前途 无可限量啊。

闲话少说,这几天小搞了下,用MySQL和flex弄了个简易随机视频聊天室,和有共同爱好的各位一起分享下。高手可以直接飞过哈,欢迎提出意见, 毕竟刚玩没多久,问题很多。

下面正式开始,程序主体主要分为3大块:

一、p2p语音视频功能模块

这个模块网上有很多教程了,Adobe官方的那个Sample就很 好。我就是以此为基础进行开发的。可能有些朋友还不是很了解,为了每个人都能搞清楚,下面针对代码详细地进行下介绍。

由于是p2p模式,每个用户既是呼叫者又是被呼叫者。更具体点,举个例子有两个人A和B打电话。A呼叫B,此时A是呼叫者,B是被呼叫者。反之B是 呼叫者,A是被呼叫者。因此在每个p2p模块中必须要有呼叫者和被呼叫者两个部分。

被呼叫部分:

001 //被呼叫 者发布监听流,以便呼叫者连接
002 listenStream = new NetStream(netConnection,NetStream.DIRECT_CONNECTIONS);
003 listenStream.addEventListener(NetStatusEvent.NET_STATUS,statusHandler);
004 listenStream.publish(username);
005 //呼叫者一旦订阅上面的监听 流,就会触发onPeerConnect事件
006 var c:Object =new Object();
007 c.onPeerConnect = function(caller:NetStream):Boolean
008 {
009 if(callState == CallReady)
010 {
011
012 //接受呼叫者发布的视频语音流
013 callState = CallRinging;
014 idManager.change(callState);
015 busyState = busyOn;
016 incomingStream = new NetStream(netConnection,caller.farID);
017 incomingStream.addEventListener(NetStatusEvent.NET_STATUS,statusHandler);
018 video =new Video();
019 video.attachNetStream(incomingStream);
020 remoteVideoDisplay.addChild(video);
021 incomingStream.play("caller");
022
023 var st:SoundTransform = new SoundTransform(speakerVolumeSlider.value);
024 incomingStream.soundTransform = st;
025 //处理呼叫的方法
026 var i:Object = new Object();
027 i.onIncomingCall = function(caller:String):void
028 {
029 if(callState != CallRinging)
030 {
031 txtInfo.text += "onIncomingCall: Wrong call state: " + callState + "\n";
032 return;
033 }
034 send_bn.enabled=true;
035 txtInfo.text +=  caller + "已经成功与您连接上\n";
036 partnername = caller;
037
038 //outgoingStream.send("onCallAccepted", username);
039 callState = CallEstablished;
040 //idManager.change(callState);
041 }
042 i.onIm = function(caller:String,text:String):void
043 {
044 txtMessage.text += caller+": "+text+"\n";
045 }
046 i.onDisconnected = function(caller:String):void
047 {
048 txtInfo.text += caller+"和你断开连接\n";
049 send_bn.enabled=false;
050 stop();
051 }
052 incomingStream.client = i;
053 //对呼叫者发布自己的语音视频流
054 outgoingStream = new NetStream(netConnection,NetStream.DIRECT_CONNECTIONS);
055 outgoingStream.addEventListener(NetStatusEvent.NET_STATUS,callee_outgoingStreamHandler);
056 outgoingStream.attachCamera(camera);
057 outgoingStream.attachAudio(mic);
058 outgoingStream.publish("callee");
059
060 return true;
061 }
062 txtInfo.text += "onPeerConnect: all rejected due to state: " + callState + "\n";
063
064 return false;
065 }
066 listenStream.client = c;
067
068
069
070 callState = CallReady;
071
072 呼叫部分:
073
074 callState = CallCalling;
075 idManager.change(callState);
076 busyState = busyOn;
077 //播放被呼叫者的监听流
078 controlStream = new NetStream(netConnection,farPeerID);
079 controlStream.addEventListener(NetStatusEvent.NET_STATUS,statusHandler);
080 controlStream.play(partnername);
081 //对被呼叫者发布自己的视频语音流
082 outgoingStream = new NetStream(netConnection,NetStream.DIRECT_CONNECTIONS);
083 outgoingStream.addEventListener(NetStatusEvent.NET_STATUS,caller_outgoingStreamHandler);
084 outgoingStream.attachCamera(camera);
085 outgoingStream.attachAudio(mic);
086 outgoingStream.publish("caller");
087 txtInfo.text += "正在与"+partnername+"建立连接\n";
088 //播放被呼叫者的视频语音流
089 incomingStream = new NetStream(netConnection,farPeerID);
090 incomingStream.addEventListener(NetStatusEvent.NET_STATUS,statusHandler);
091 video =new Video();
092 video.attachNetStream(incomingStream);
093 remoteVideoDisplay.addChild(video);
094 incomingStream.play("callee");
095
096 var st:SoundTransform = new SoundTransform(speakerVolumeSlider.value);
097 incomingStream.soundTransform = st;
098 //处理呼叫的方法
099 var i:Object = new Object();
100 i.onIm = function(callee:String,text:String):void
101 {
102 txtMessage.text += callee+": "+text+"\n";
103 }
104 i.onCallAccepted = function(callee:String):void
105 {
106 if (callState != CallCalling)
107 {
108 txtInfo.text += "连接失 败";
109 return;
110 }
111 send_bn.enabled=true;
112 txtInfo.text += callee+"已经成功与您连接上\n";
113 callState = CallEstablished;
114 //idManager.change(callState);
115 }
116 i.onDisconnected = function(callee:String):void
117 {
118 txtInfo.text += callee+"和你断开连接\n";
119 send_bn.enabled=false;
120 stop();
121 }
122 incomingStream.client = i;

二、用户数据库及webservice接口

这个项目我使用MySQL进行用户数据库设计,用户端产生相应行为后(如登录,下线,聊天,空闲等)会在数据库中更新自己的状态,其他用户根据查询得到的 结果进行操作。数据库结构见下图:

用户 名           peerID        更新时间              在线状态    聊天状态

该项目只要进行简单的数据库操作就可以了,所以我使用了HTTPService组件和一个简单的php网页进行与数据库的交互。

HTTPService组件位于mx.rpc.http包下,当调用 HTTPService 对象的 send() 方法时,将发出对指定 URL 的 HTTP 请求,并且返回 HTTP 响应。可以选择向指定 URL 传递参数。项目中通过HTTPService组件传递用户端的参数到php网页,由php根据相应的参数操作数据库,返回相应的结果交由用户端执行。

HTTPService组件部分:

1 mHttpService = new HTTPService();
2 mHttpService.url = mWebServiceUrl;
01 //添加对结果时间的侦听
02 mHttpService.addEventListener("result", httpResult);
03 mHttpService.addEventListener("fault", httpFault);
04 //实例化request请求对象并发送
05 var request:Object = new Object();
06 var now:Date = new Date();
07 request.time = now.getTime();
08 request.username = user;
09 request.identity = id;
10 request.online = x;
11 request.busy = x;
12 mHttpService.cancel();
13 mHttpService.send(request);

php网页部分:

01 <?php
02 $output = "<?xml version=\"1.0\" encoding=\"utf-8\"?>";
03 $output .= "<result>";
04 if ( isset($_GET["username"]) || isset($_GET["friends"]) || isset($_GET["fetch"]))
05 {
06 define( "DATABASE_SERVER", "localhost" );
07 define( "DATABASE_USERNAME", "root" );
08 define( "DATABASE_PASSWORD", "root");
09 define( "DATABASE_NAME", "root" );
10 $mysql = mysql_connect( DATABASE_SERVER,
11 DATABASE_USERNAME,
12 DATABASE_PASSWORD )
13 or die( mysql_error() );
14 mysql_select_db( DATABASE_NAME );
15 }
16 //注册更新部分
17 if ( isset($_GET[ "username" ]) )
18 {
19
20 $user   = mysql_real_escape_string( $_GET[ "username" ] );
21 $identity   = mysql_real_escape_string( $_GET[ "identity" ] );
22 $online = mysql_real_escape_string( $_GET[ "online" ] );
23 $busy = mysql_real_escape_string( $_GET[ "busy" ] );
24
25 $query = "SELECT * FROM registrations WHERE m_username='$user' ;";
26 $result = mysql_query( $query );
27
28 $isNew = ($result && mysql_num_rows($result) == 0);
29 if( $isNew ) {
30 $query = "INSERT INTO registrations SET ";
31 $query .= "m_username='$user', m_identity='$identity', m_updatetime=now(), m_online='$online', m_busy='$busy';";
32 } else {
33 $query = "UPDATE registrations SET ";
34 $query .= " m_identity='$identity', m_updatetime=now(), m_online='$online', m_busy='$busy' where m_username='$user';";
35 }
36 $result = mysql_query( $query );
37 if( $isNew )
38 $output .= "<update>true</update>";
39 else
40 $output .= "<update>false</update>";
41 }
01 //查找用户部分
02 if ( isset($_GET[ "friends" ]) )
03 {
04 $friends    = mysql_real_escape_string( $_GET[ "friends" ] );
05 $output .= "<friend><user>$friends</user>";
06 $query = "select * from registrations where m_username = '$friends' and TIMEDIFF(now(),m_updatetime) >0 ;";
07
08 $result = mysql_query( $query );
09 if( $result ) {
10 while( $item = mysql_fetch_assoc( $result ) ) {
11 $output .= "<identity>".$item["m_identity"]."</identity>";
12 }
13 }
14 $output .= "</friend>";
15 }
01 //获取返回结果
02 if ( isset( $_GET["fetch"]) )
03 {
04 $time = mysql_real_escape_string( $_GET[ "time" ] );
05 $query = "select m_number from registrations order by m_username asc ;" ;
06
07 $result =mysql_query($query);
08 if( $result )
09 {
10 $num = mysql_num_rows($result);
11 $output .= "<fetch><num>".$num."</num>";
12 }
13
14 $query = "select m_username from registrations where m_online ='1' and m_busy = '0' order by m_username asc ;";
15 $result = mysql_query($query);
16
17 if( $result )
18 {
19 $onlinenum = mysql_num_rows($result);
20 $output .="<onlinenum>".$onlinenum."</onlinenum><users>";
21 $i = 1;
22 while ($row = mysql_fetch_row($result))
23 {
24 $output .= "<user".$i.">".$row[0]."</user".$i.">";
25 $i++;
26 }
27 $output .= "</users></fetch>";";
28 }
29 }
30
31
32
33
34 $output .= "</result>";
35
36 header( "Content-Type: text/xml" );
37 echo $output;
38 ?>

三、主程序部分

主程序界面实时显示在线用户状态,可以双击列表空闲用户进行聊天 也可以点击随机按钮随机选取在线空闲用户进行聊天。

退出时记得点击离开正常退出哈。

Demo:http://p2pchat.online.cm/

这个免费空间貌似有广告,不点它就是了

有问题欢迎交流-_-

赞(0) 打赏
分享到: 更多 (0)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏