Strauts P2P VideoPhoneP2pDemo 代码浅析

                                       Strauts P2P VideoPhoneP2pDemo  代码浅析

                                                             from:飞UU梦

     前些天把Adobe官方的p2p Video phone demo的研究了一遍,了解了这个基于Stratusvideo phone是如何工作的。由于Adobedemo需要运行一个python写的web service才可以运行这个web service用于用户名与peer ID之间的转换,真实项目中我们不可能用256-bit peer ID作为联系人的用户名,所以做一个用户名到Peer ID之间的转换是很用必要的,打电话时只需要知道对方的登陆用户名就可以联系,不需要知道这个超长的不可能记住的Peer ID。可能很多不熟悉python的人没有成功运行源代码,现在我就从我的角度告诉大家如何创建这么一个 P2P 电话。(当然不需要额外的web service)

首先还是了解一些必要的知识

RTMFP — RTMFP
Adobe公司开发的一套新的通信协议,该协议可以让使用Adobe Flash Player的终端用户之间进行直接通信, RTMFP基于UDPFlash Media Service支持的RTMP是基于TCP的。

Stratus — Adobe Stratus service beta
是支持RTMFP 的服务器。它是一个中转式的服务,它的作用是建立flash player之间的通讯。即使它们位于NATs的后面。与FMS不同,Stratus不支持媒体转播,共享对象,脚本等等,你只能开发客户端之间直接联系的应用程序。

我们的网络电话就是基于上面描述的技术,在开始之前有一些准备工作要做。

确定你安装了 Flex SDK3.2. 这里下载
确定安装了flash payer 10 debug version (开发环境最好用debug version) 这里下载
申请一个 Stratus develper key 这里申请
新建一个项目,名字随意,位置随意,编辑项目属性 — Flex compiler — Require Flash player version 10:0:0

1.
首先了解一下我们会用到的变量, 这里要最主要的四个NetStream,他们的作用请看注释。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

//链接Adobe stratus 服务器

private const StratusAddress:String = "rtmfp://stratus.adobe.com";

 

//Developer Key,如果没有请根据Flex 迷你教程 -- 基于StratusP2P网络电话 (1)中的提示申请

private const DeveloperKey:String = "xxxxxx";

 

//我们需要一个nectConnetionstratus 服务器链接

private var netConnection:NetConnection;

 

//用于对外发布自己的身份信息流

private var myStream:NetStream;

 

//用于链接后对外发布自己的信息流,比如音频,视频,文字

private var outgoingStream:NetStream;

 

//进入的信息流,这个流对应呼叫者的outgoingStream,用这个流尝试播放发布者发布的信息,比如音频,视频,文字

private var incomingStream:NetStream;

 

//用于尝试播放被呼叫者的身份信息流myStream发送的信息,被呼叫者在发送自己的身份信息流时会监听呼叫者对myStream的播放请求

private var controlStream:NetStream;


2.
下面是主要用到的方法。

呼叫者的主要方法/事件触发顺序,

init()
netConnectionHandler() — case “NetConnection.Connect.Success”:
initSendStream();
call();
onConnectSuccess()
onIm()

被呼叫者主要方法/事件的调用触发顺序

init()
netConnectionHandler() — case “NetConnection.Connect.Success”:
initSendStream();
onPeerConnect();
onIncomingCall();
onIm();

3. Demo (
请打开两个浏览器进行Demo) :

操作方法:

任意填写用户名,点击链接。
在另一个浏览器同样登陆。
用其中一个的peerid作为链接ID呼叫对方。
链接成功后可以信息聊天。
4.
源代码下载与主要方法代码,学习请看注释,写的很清楚

输入用户名,点击链接时触发下面的代码

1
2
3
4
5
6
7
8
9
10
11
12

//链接 adobe stratus 服务器

private function init():void{

 

        if(userName.text == "")

        {

               Alert.show("请输入任意用户名","错误")

               return

        }

        netConnection = new NetConnection();

        netConnection.addEventListener(NetStatusEvent.NET_STATUS, netConnectionHandler);

        netConnection.connect(StratusAddress + "/" + DeveloperKey); //服务器地址里需要开发者Key

}


STRATUS链接成功后在CASE “NETCONNECTION.CONNECT.SUCCESS”里调用下面的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

private function initSendStream():void{

 

        //这三行表示我对外发布一个名称为netConnection.nearID的流,呼叫者通过我的nearID与我链接后,如果播放

        //这个名称为netConnection.nearID的流,会出发onPeerConnect事件,这样我就知道有人链接我

        myStream = new NetStream(netConnection, NetStream.DIRECT_CONNECTIONS);

        myStream.addEventListener(NetStatusEvent.NET_STATUS, netStreamHandler);

        myStream.publish(netConnection.nearID);

 

        //监听onPeerConnect事件

        var o:Object = new Object();

        o.onPeerConnect = function(subscriberStream:NetStream):Boolean

        {

               //当我收到呼叫者的链接请求后,尝试播放呼叫者的流名为"caller"的流,farID代表呼叫者的唯一ID,也就是前面提到的nearID

               //我通过farID找到呼叫者

            incomingStream = new NetStream(netConnection,subscriberStream.farID);

        incomingStream.addEventListener(NetStatusEvent.NET_STATUS, incomingStreamHandler);

        incomingStream.play("caller");

 

        //监听onIm事件,用于收取文字信息

        var i:Object = new Object;

        i.onIm = function(name:String, value:String):void

        {

            info.text += name + ": " + value + "/n";

        }

        //监听onIncomingCall事件,用于确定链接成功

        i.onIncomingCall = function(name:String):void

        {

               //显示链接成功后,对呼叫者发布我的信息流,名称为callee

            info.text += name + " 已经与你链接/n";

            outgoingStream = new NetStream(netConnection, NetStream.DIRECT_CONNECTIONS);

                outgoingStream.addEventListener(NetStatusEvent.NET_STATUS, outgoingStreamHandler);

                outgoingStream.publish("callee");

                outgoingStream.send("onConnectSuccess",userName.text);

 

        }

        incomingStream.client = i;

 

        return true;

        }

 

        myStream.client = o;

}


呼叫者输入对方PEERID,点击呼叫后执行下面的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

private function call():void{

 

    //通过对方的peerId链接被呼叫者,播放对方的身份信息流

    controlStream = new NetStream(netConnection,peerId.text);

    controlStream.addEventListener(NetStatusEvent.NET_STATUS, netStreamHandler);

    controlStream.play(peerId.text);

 

    //同时对外发布呼叫者的信息流

    outgoingStream = new NetStream(netConnection, NetStream.DIRECT_CONNECTIONS);

    outgoingStream.addEventListener(NetStatusEvent.NET_STATUS, outgoingStreamHandler);

    outgoingStream.publish("caller");

 

    //尝试播放被呼叫者的信息流

    incomingStream = new NetStream(netConnection, peerId.text);

    incomingStream.addEventListener(NetStatusEvent.NET_STATUS, incomingStreamHandler);

    incomingStream.play("callee");

    info.text += "正在呼叫,请稍候...... /n/n"

 

    //监听信息发布事件

    var i:Object = new Object;

    i.onIm = function(name:String, value:String):void

    {

        info.text += name + ": " + value + "/n";

    }

    //监听onConnectSuccess事件,确定链接成功

     i.onConnectSuccess = function(name:String):void

    {

        info.text += ""+name + "链接成功/n";

    }

 

    incomingStream.client = i

 

}


被呼叫者在收到呼叫时执行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

o.onPeerConnect = function(subscriberStream:NetStream):Boolean

{

        //当我收到呼叫者的链接请求后,尝试播放呼叫者的流名为"caller"的流,farID代表呼叫者的唯一ID,也就是前面提到的nearID

        //我通过farID找到呼叫者

    incomingStream = new NetStream(netConnection,subscriberStream.farID);

    incomingStream.addEventListener(NetStatusEvent.NET_STATUS, incomingStreamHandler);

    incomingStream.play("caller");

 

    //监听onIm事件,用于收取文字信息

    var i:Object = new Object;

    i.onIm = function(name:String, value:String):void

    {

        info.text += name + ": " + value + "/n";

    }

    //监听onIncomingCall事件,用于确定链接成功

    i.onIncomingCall = function(name:String):void

    {

        //显示链接成功后,对呼叫者发布我的信息流,名称为callee

        info.text += name + " 已经与你链接/n";

        outgoingStream = new NetStream(netConnection, NetStream.DIRECT_CONNECTIONS);

        outgoingStream.addEventListener(NetStatusEvent.NET_STATUS, outgoingStreamHandler);

        outgoingStream.publish("callee");

        outgoingStream.send("onConnectSuccess",userName.text);

 

    }

    incomingStream.client = i;

 

    return true;

}


呼叫者与被呼叫者链接成功后执行

1
2
3
4
5

//监听onConnectSuccess事件,确定链接成功

i.onConnectSuccess = function(name:String):void

{

    info.text += ""+name + "链接成功/n";

}


发送信息与接收信息代码

1
2
3
4
5
6
7
8
9
10
11
12

//outgoingStream对外发布信息流

private function send():void{

   info.text += userName.text + ": " + message.text + "/n";

    outgoingStream.send("onIm",userName.text,message.text);

}

 

//监听信息发布事件

var i:Object = new Object;

i.onIm = function(name:String, value:String):void

{

    info.text += name + ": " + value + "/n";

}

 

你可能感兴趣的:(Strauts P2P VideoPhoneP2pDemo 代码浅析)