Flex中NetConnection与NetStream的关系、及浏览器并发连接数测试[转]

最近在做一个基于BS结构的视频会议系统,决定采用开源的FluorineFx.net与Flex结合的方法进行开发,前期开发都非常顺利,包括同步白板等。但到了实时视频传输的时候,原本设计是每个客户端可以显示三路视频,但到IIS上测试的时候,发现状态很不稳定,偶尔可以全部显示出来,大部分情况下,客户端总是随机显示一个或两个。查询了ActionScript的技术文档、FluorineFx的技术文档等,也没有找出与这个问题相关的描述,包括网络上,对NetConnection与NetStream的对应关系也没有很肯定的说明或总结。程序中实在找不出问题的所在,我初步怀疑是浏览器并发连接数限制的问题导致无法在内置于浏览器的swf中同时连接多路视频,于是决定将这部分抽象出来,专门做一个测试,测试选择了三个比较具有代表性的浏览器进行。

开发环境:VS2008(FluorineFx.Net)与FlexBuilder3

测试环境:IE 8,Chrome,FF + Flash player 11 Debug版

  一、测试用的流处理服务程序编写

首先利用Vs 2008新建了一个FluorineService项目,并添加应用程序适配器类,在RTMP连接AppConnect时用来判断连接的合法性,即只有当rtmp连接的parameters[1]为"000"的连接请求才允许连接服务器上的rtmp信道端口,如下:

using FluorineFx;using FluorineFx.Messaging.Adapter;using FluorineFx.Messaging.Api;using FluorineFx.Messaging.Api.SO;

namespace OnLineService{    public class DemoApp:ApplicationAdapter    {

       public override bool AppConnect(IConnection connection, object[] parameters)        {            string userName = parameters[0] as string;            string password = parameters[1] as string;

            // 这里可以自定义登录判断验证逻辑,此处只要密码为000即可进入            if (password != "000")                return false;            return true;        }

     }

}

新建一个FluorineFx Web后,修改其Web-INF/Flex文件夹下的services-config.xml文档,指定rtmp传输信道所用的端口:

        <channel-definition id="my-rtmp" class="mx.messaging.channels.RTMPChannel">            <endpoint uri="rtmp://{server.name}:2037" class="flex.messaging.endpoints.RTMPEndpoint"/>            <properties>                <idle-timeout-minutes>20</idle-timeout-minutes>            </properties>        </channel-definition>

在FluorineFx Web项目根目录下添加apps文件夹,在apps下添加OnLineUser文件夹,在OnLineUser下添加app.config配置文件及一个streams文件夹,streams下放入五个flv视频文件(我这里自己随便用Flex写的小程序采集了一小段视频,并复制成5份放在这个文件夹下,分别命名为mytest1...)

在app.config中指定流处理的服务程序为DemoApp,如下:

<?xml version="1.0" encoding="utf-8"?><configuration>  <application-handler type="OnLineService.DemoApp"/></configuration>

编译后启动调试,使Asp.Net Development Server处于运行状态(以提供流处理的服务)

二、测试用Flex项目的开发
    打开Flex Builder3后,新建一个Flex项目,项目路径设置在“一”中建立的FluorineFx Web项目的根目录下的Flex目录,并引入相关libs与编译参数,如下图所示:

然后将mxml文件编写如下:

<?xml version="1.0" encoding="utf-8"?><mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"      width="1254" height="246" backgroundGradientAlphas="[1.0, 1.0]"     backgroundGradientColors="[#000000, #049FF1]" fontSize="12" initialize="init()"><mx:HBox id="hbox" x="10" y="31" width="1234" height="187"></mx:HBox><mx:Script source="FiveConnFiveStream.as"/></mx:Application>

添加一个FiveConnFiveStream.as文件,在其下建立五个NetConnection与五个NetStream,分别连接到“一”中的五个视频文件,如下:

import flash.events.NetStatusEvent;import flash.net.NetConnection;import flash.net.NetStream;import mx.controls.VideoDisplay;import mx.messaging.config.ServerConfig;private var rtmpChanner:String;private var nc:NetConnection;private var nc2:NetConnection;private var nc3:NetConnection;private var nc4:NetConnection;private var nc5:NetConnection;private var ns1:NetStream;private var ns2:NetStream;private var ns3:NetStream;private var ns4:NetStream;private var ns5:NetStream;

private function init():void{    rtmpChanner=ServerConfig.getChannel("my-rtmp").endpoint+"/OnLineUser";    nc=new NetConnection();    nc.addEventListener(NetStatusEvent.NET_STATUS,OnConnHandler);    nc.client=this;    nc.connect(rtmpChanner,"adsfasdf","000");

    nc2=new NetConnection();    nc2.addEventListener(NetStatusEvent.NET_STATUS,OnConnHandler2);    nc2.client=this;    nc2.connect(rtmpChanner,"adsfadasdf","000");

    nc3=new NetConnection();    nc3.addEventListener(NetStatusEvent.NET_STATUS,OnConnHandler3);    nc3.client=this;    nc3.connect(rtmpChanner,"adsfffasdf","000");

    nc4=new NetConnection();    nc4.addEventListener(NetStatusEvent.NET_STATUS,OnConnHandler4);    nc4.client=this;    nc4.connect(rtmpChanner,"adfgg","000");

    nc5=new NetConnection();    nc5.addEventListener(NetStatusEvent.NET_STATUS,OnConnHandler5);    nc5.client=this;    nc5.connect(rtmpChanner,"adfaaa","000");}    

private function OnConnHandler(event:NetStatusEvent):void{    trace("连接一状态:"+event.info.code);    if(event.info.code=="NetConnection.Connect.Success")    {      var vds:VideoDisplay=new VideoDisplay();      vds.height=160;      vds.width=240;      var vd:Video=new Video();      vd.width=240;      vd.height=160;      this.ns1=new NetStream(this.nc);      this.ns1.addEventListener(NetStatusEvent.NET_STATUS,OnStreamHandler1);      vd.attachNetStream(this.ns1);      this.ns1.client=this;      this.ns1.play("mytest1");      vds.addChild(vd);      this.hbox.addChild(vds);      trace("播放一");}        }

private function OnConnHandler2(event:NetStatusEvent):void{    trace("连接二状态:"+event.info.code);    if(event.info.code=="NetConnection.Connect.Success")    {      var vds2:VideoDisplay=new VideoDisplay();      vds2.height=160;      vds2.width=240;      var vd2:Video=new Video();      vd2.width=240;      vd2.height=160;      this.ns2=new NetStream(this.nc2);      this.ns2.addEventListener(NetStatusEvent.NET_STATUS,OnStreamHandler2);      vd2.attachNetStream(this.ns2);      this.ns2.client=this;      this.ns2.play("mytest2");      vds2.addChild(vd2);      this.hbox.addChild(vds2);      trace("播放二");    }}

private function OnConnHandler3(event:NetStatusEvent):void{    trace("连接三状态:"+event.info.code);    if(event.info.code=="NetConnection.Connect.Success")    {      var vds3:VideoDisplay=new VideoDisplay();      vds3.height=160;      vds3.width=240;      var vd3:Video=new Video();      vd3.width=240;      vd3.height=160;      this.ns3=new NetStream(this.nc3);      this.ns3.addEventListener(NetStatusEvent.NET_STATUS,OnStreamHandler3);            vd3.attachNetStream(this.ns3);      this.ns3.client=this;      this.ns3.play("mytest3");      vds3.addChild(vd3);      this.hbox.addChild(vds3);      trace("播放三");    }}

private function OnConnHandler4(event:NetStatusEvent):void{    trace("连接四状态"+event.info.code);    if(event.info.code=="NetConnection.Connect.Success")    {      var vds4:VideoDisplay=new VideoDisplay();      vds4.height=160;      vds4.width=240;      var vd4:Video=new Video();      vd4.width=240;      vd4.height=160;      this.ns4=new NetStream(this.nc4);      this.ns4.addEventListener(NetStatusEvent.NET_STATUS,OnStreamHandler4);      vd4.attachNetStream(this.ns4);      this.ns4.client=this;      this.ns4.play("mytest4");      vds4.addChild(vd4);      this.hbox.addChild(vds4);      trace("播放四");    }}

private function OnConnHandler5(event:NetStatusEvent):void{    trace("连接五状态"+event.info.code);    if(event.info.code=="NetConnection.Connect.Success")    {      var vds5:VideoDisplay=new VideoDisplay();      vds5.height=160;      vds5.width=240;      var vd5:Video=new Video();      vd5.width=240;      vd5.height=160;      this.ns5=new NetStream(this.nc5);      this.ns5.addEventListener(NetStatusEvent.NET_STATUS,OnStreamHandler5);      vd5.attachNetStream(this.ns5);      this.ns5.client=this;      this.ns5.play("mytest5");      vds5.addChild(vd5);      this.hbox.addChild(vds5);      trace("播放五");    }}

private function OnStreamHandler1(event:NetStatusEvent):void{    trace("流一状态:"+event.info.code);}private function OnStreamHandler2(event:NetStatusEvent):void{    trace("流二状态:"+event.info.code);}private function OnStreamHandler3(event:NetStatusEvent):void{    trace("流三状态:"+event.info.code);}private function OnStreamHandler4(event:NetStatusEvent):void{    trace("流四状态:"+event.info.code);}private function OnStreamHandler5(event:NetStatusEvent):void{    trace("流五状态:"+event.info.code);}

三、开始测试
  在FlexBuilder中Builder后,进行Debug调试。

此时,我们就可以看到在浏览器中已经可以实时加载视频了,为了我们测试的目的与结果,我们要设计如下几种测试以验证结果及进行对比:

a、排除服务器的因素,即服务器是否能提供多个并发连接的能力(以证明客户端有的实时视频显示不出非服务器的原因引起)

b、场景一:在Flex中建立5个NetConnection与5个NetStream,5个NetStream分别指向5个视频文件(验证客户端连接建立能力及每个连接加载实时流后,浏览器可维持的连续的并发连接的能力)

c、场景二:在Flex中建立5个NetConnection与5个NetStream,5个NetStream同时指向一个视频文件(验证是否可以将多个连接的并发连接同时关联服务器上同一个文件)

d、场景三:在Flex中建立1个NetConnection,并以这个NetConnection建立5个NetStream,分别测试指向一个视频文件与5个视频文件时的表现

e、场景四:将bcd中的五个都改为3个连接与3个流做对比测试

(“二”为b场景一的as代码,其它场景的在附件中有,这里不一一列出。)

注:以上几个场景,除a外,其它都分别编译后,在IE8,FF,Chrome中进行测试(IE的话还需要对注册表中连接数进行修改再次测试),每个单独的测试刷新10次,记录客户端实时连接并成功显示的视频数,并且为了排除缓存的影响,每次测试前都清空各个浏览器的缓存。

首先排除服务器的影响,我们对服务器进行连接的压力测试,同时打开多个浏览窗口,同时连接这个应用,看是不是可以支持多于5路的视频传输,测试效果如下(排除服务器因素,证明FlourineFx.Net并没有论坛中所言的连接性能诡异的问题,但这并不是压力测试,我这里的目的只是为了证明服务器的rtmp应用程序适配器可以支持5路以上的实时连接,下图中三个浏览器同时打开,并访问这个应用,可以轻易看到10个连接)

以下为随机截取的几个测试场景的图片与Flex Builder Console中的输出情况

(IE8在没有修改注册表连接数前,用5个连接与5个NetStream连接服务器时的情况,成功进行了4个并发的实时连接)

(在Flex中只用一个NetConnection,建立5个NetStream,不管是连接一个文件还是5个文件,在各个浏览器中,都只有最后一个NetStream可以成功连接上,由此证明,如果要连接实时视频数据流时,一个NetConnection只能与一个NetStream相关联,如下图)

四、测试结果统计

以下为测试结果的统计表格:

IE8在没有修改注册表连接数之前:

IE8修改注册表,将连接数改为10之后

(IE8的注册表连接数修改:HKEY_CURRENT_USER/SoftWare/Microsoft/Windows/CurrentVerSion/InternetSettings下添加两个DWORD,MaxConnectionsPer1_OServer与MaxConnectionsPerServer,分别指定其值即可指定连接数,如下:

)

Chrome的测试数据

FF的测试数据

五,总结

1、在Flex开发中,一个NetConnection只能在同一时间被一个NetStream占用,用来传输实时数据

2、现在的浏览器一般都至少能稳定地支持两个并发连接,但跟某些网站上所言的,支持几个并发连接的能力,并不是稳定的,在我上述的测试中,五个NetConnection都可以建立成功,但若利用这些连接通道同时并发传输数据,并不能保证每次都能成功建立起这些并发连接。

另附:我查阅了一下HTTP/1.1 RFC中的相关章节8.1.4,其中规定单客户端与任何服务器或代理的连接不应超过两个(single-user client SHOULD NOT maintain more than 2 connections with any server or proxy.)。但现在的浏览器基本上都超过了这个并发连接数,以下为国外某网站上列出的各浏览器支持的并发连接数表格截图:

但经过我上面的测试发现,对于并发的且长时间被占用的连接,浏览器一般只能稳定地支持两个,不管是IE\Chrome\FF,都是如此,或许浏览器方所宣称的支持多路并发连接的能力,是对于那些突发式的、不需要长时间占用这个连接来传送大量数据而言的。

做以上测试花了一上午时间,因此写个总结在这里。原创文章,转载请注明一下。观点可能有些片面,不正确之处望指正。

附:测试中用的源文件下载 (注:以上不同的测试场景请修改mxml中引入不同的as文件)

分类: Flex与ActionScript3学习笔记FlourineFx.net使用心得

标签: FlexNetConnection与NetStream的对应关系FluorineFluorineFx.Net实时视频浏览器并发连接

时间: 2024-10-12 22:00:23

Flex中NetConnection与NetStream的关系、及浏览器并发连接数测试[转]的相关文章

如何在Chrome中方便快捷地切换分辨率(Chrome浏览器分辨率测试)

如何在Chrome中方便快捷地切换分辨率?使用Chrome插件Resolution Test!!! 1.下载Chrome插件Resolution Test.crx 2.浏览器--更多工具--扩展程序页面--开发者模式 3.将Resolution Test.crx用鼠标拖放到扩展程序页面 4.Chrome会弹出安装插件的提示.点击继续即可完成!在浏览器的网址栏后会显示该插件图标! 5.选择(是点击不是勾选!)目标分辨率,就可以将当前Chrome的窗口大小设置为目标分辨率大小. 6.可以选择多个分辨

SharedObject使用:在FluorineFx.net与Flex中使用共享对象维护在线用户列表实例【转】

一.添加一个新的FluorineFx的服务类项目OnLineService,删除原有的Sample.cs,并添加一个用户类定义与一个ApplicationAdpater类:如下: /*-- User.cs --*/ namespace OnLineService { public class User { public string UserName { get; set; } public string UserPsw { get; set; } } } /* --  ApplicationA

Flash, Flex, Air, Flashplayer之间的相互关系是什么

Flash, Flex, Air, Flashplayer之间的相互关系是什么? 著作权归作者所有. 商业转载请联系作者获得授权,非商业转载请注明出处. 作者:曾嵘 链接:http://www.zhihu.com/question/20001256/answer/15565376 来源:知乎ActionScript ActionScript通常简称为AS,它是Flash平台的语言.AS编写的程序,最终可以编译成SWF.SWC.SWF就是我们常说的Flash动画.但是现在SWF已经不仅仅是动画,而

Flex中设置Camera的视频清晰质量的最佳配合

今天需要设置Flex中的Camera组件的一些属性,后来发现清晰度不是很高,于是捣鼓了上午半天,设置了很多的参数,竟然发现手册上就是有现成的一些设置方法,郁闷!不过我还是专门设置了几个有用和必要的属性,为自己的程序中应用,其实很简单! 以此为例: Camera.setMode(320,240,15); 就是要设置一个宽320.高240.播放速率是15fps,他的带宽消耗: (320*240*15)/1000000 = 1.2(Mbps) = 1152000(Bps)//1000000是1024*

详细介绍Flex中操作XML

一  在介绍Flex中操作XML之前,首先简单介绍下XML中的基本术语. 元素:XML中拥有开始标签和结束标签的这一块称为“元素”    节点:把XML元素与文本结合起来统称为节点    根节点:位于整个XML文当顶端的节点    文本节点:包含文本的节点    属性:元素的组成部分,以键/值形式放在元素标签内 用一个例子来说明 <root_node><!--这是一个根节点也是一个元素--> <node attribute="value"><!

[2]工欲善其事必先利其器-------UML中的几种常见关系(二)

目录 1.UML类图中几种常见的关系 经过(一)中介绍,我选择的是StarUML作为UML的学习工具,个人喜好,至少在功能上能够满足我现在的需求, 在介绍StarUML的使用之前首先介绍下UML中几种常见的关系: UML类图中常见的关系按照关系的强弱可分为:泛化 ,实现 ,组合, 聚合 , 依赖这几种 1.泛化关系:是一种继承关系,也就是XX is a kind of XX 描述. 2.实现关系:是一种类与接口的关系. 3. 组合关系:是一种强关联,属于一种整体与部分的关系,但是部分不能离开整体

Flex中的DataGrid报错(一)

1.错误描述    此行的多个标记: -holeNum -1105: 赋值的目标必须是引用值. 2.错误原因    detailWindow.holeNum.toString() = "20140730"; 3.解决办法 Flex中的DataGrid报错(一),布布扣,bubuko.com

Flex中的DataGrid报错(二)

1.错误描述 此行的多个标记: -holeNum -1067: String 类型值的隐式强制指令的目标是非相关类型 mx.controls:Text. 2.错误原因  将字符串类型赋值给Text类型 3.解决办法 Flex中的DataGrid报错(二),布布扣,bubuko.com

linux中权限和命令的关系。

我们知道权限对於使用者帐号来说是非常重要的,因为他可以限制使用者能不能读取/创建/删除/修改文件或目录. 一.让使用者能进入某目录成为『可工作目录』的基本权限为何: 可使用的命令:例如 cd 等变换工作目录的命令: 目录所需权限:使用者对这个目录至少需要具有 x 的权限 额外需求:如果使用者想要在这个目录内利用 ls 查阅档名,则使用者对此目录还需要 r 的权限. 二.使用者在某个目录内读取一个文件的基本权限为何? 可使用的命令:例如本章谈到的 cat, more, less等等 目录所需权限: