<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Derek J Entringer &#124; Interactive Media, Web Application, and Mobile App Developer &#187; actionscript</title>
	<atom:link href="http://www.derekentringer.com/blog/tag/actionscript/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.derekentringer.com/blog</link>
	<description>Interactive Media Development, Web Application Development, Mobile App Development, Flash, Flash Media Server, Flex, Flash Component Creation, Game Programming &#38; Design, Blog, CMS, eCommerce Setup &#38; Styling, Search Engine Optimization, Social Networking Strategies, Website Interface &#38; Template Creation, Windows Vista Gadget Development, Apple Widget Development, Email Marketing, Code Samples, Tutorials</description>
	<lastBuildDate>Tue, 13 Jul 2010 19:25:15 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>FLV Player &#8211; Flash Video Component &#8211; Now Available at FLVplayer.com</title>
		<link>http://www.derekentringer.com/blog/flv-player-flash-video-component-now-available-at-flvplayercom/</link>
		<comments>http://www.derekentringer.com/blog/flv-player-flash-video-component-now-available-at-flvplayercom/#comments</comments>
		<pubDate>Fri, 24 Jul 2009 08:39:29 +0000</pubDate>
		<dc:creator>Derek J Entringer</dc:creator>
				<category><![CDATA[Code Samples]]></category>
		<category><![CDATA[Flash]]></category>
		<category><![CDATA[Flash Components]]></category>
		<category><![CDATA[New Developments]]></category>
		<category><![CDATA[actionscript]]></category>
		<category><![CDATA[component]]></category>
		<category><![CDATA[devbase.com]]></category>
		<category><![CDATA[flv]]></category>
		<category><![CDATA[flvplayer.com]]></category>
		<category><![CDATA[player]]></category>
		<category><![CDATA[progressive]]></category>
		<category><![CDATA[streaming]]></category>
		<category><![CDATA[video]]></category>

		<guid isPermaLink="false">http://www.derekentringer.com/blog/?p=298</guid>
		<description><![CDATA[
			
				
			
		

After a recent partnership with FLVplayer.com, and a lot of work developing and tweaking our latest product, we&#8217;ve officially released our highly customizable FLV Player Flash Video Component. Have a look at flvplayer.com
FLVplayer supports all of the video formats available through the Adobe Flash platform including, but not limited to, MOV, MP4, F4V, and of course FLV.
Customize FLVplayer to match the look and feel of your current website or project. Modify the component to give it your own custom interface.
Our FLVplayer is loaded with features. If you&#8217;re a seasoned programmer, ...]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="clear:left; float:left; margin-top:10px; margin-bottom: 10px; margin-right:12px; margin-left:2px;">
			<a href="http://www.derekentringer.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2FwaS50d2VldG1lbWUuY29tL3NoYXJlP3VybD1odHRwJTNBJTJGJTJGd3d3LmRlcmVrZW50cmluZ2VyLmNvbSUyRmJsb2clMkZmbHYtcGxheWVyLWZsYXNoLXZpZGVvLWNvbXBvbmVudC1ub3ctYXZhaWxhYmxlLWF0LWZsdnBsYXllcmNvbSUyRg=="><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.derekentringer.com%2Fblog%2Fflv-player-flash-video-component-now-available-at-flvplayercom%2F&amp;source=derekentringer&amp;style=normal&amp;service=TinyURL.com" height="61" width="50" /><br />
			</a>
		</div>
<p><!--PLAIN_TEXT--><br />
After a recent partnership with FLVplayer.com, and a lot of work developing and tweaking our latest product, we&#8217;ve officially released our highly customizable FLV Player Flash Video Component. Have a look at flvplayer.com</p>
<p>FLVplayer supports all of the video formats available through the Adobe Flash platform including, but not limited to, MOV, MP4, F4V, and of course FLV.</p>
<p>Customize FLVplayer to match the look and feel of your current website or project. Modify the component to give it your own custom interface.</p>
<p>Our FLVplayer is loaded with features. If you&#8217;re a seasoned programmer, use our API to extend the options, and create engaging multimedia video.</p>
<p><center><br />
<script language="JavaScript" type="text/javascript">
	AC_FL_RunContent(
		'codebase', 'http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=10,0,0,0',
		'width', '570',
		'height', '316',
		'src', 'http://www.derekentringer.com/blog/flvplayer/FLVplayer',
		'quality', 'high',
		'pluginspage', 'http://www.adobe.com/go/getflashplayer',
		'align', 'middle',
		'play', 'true',
		'loop', 'true',
		'scale', 'showall',
		'wmode', 'window',
		'devicefont', 'false',
		'id', 'FLVplayer',
		'bgcolor', '#0F0F0F',
		'name', 'FLVplayer',
		'menu', 'false',
		'allowFullScreen', 'true',
		'allowScriptAccess','sameDomain',
		'movie', 'http://www.derekentringer.com/blog/flvplayer/FLVplayer',
		'salign', ''
		); //end AC code
</script><br />
<noscript><br />
	<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=10,0,0,0" width="570" height="316" id="FLVplayer" align="middle"><param name="allowScriptAccess" value="sameDomain" /><param name="allowFullScreen" value="false" /><param name="movie" value="http://www.derekentringer.com/blog/flvplayer/FLVplayer.swf" /><param name="menu" value="false" /><param name="quality" value="high" /><param name="bgcolor" value="#0F0F0F" /><embed src="http://www.derekentringer.com/blog/flvplayer/FLVplayer.swf" menu="false" quality="high" bgcolor="#0F0F0F" width="570" height="316" name="FLVplayer" align="middle" allowScriptAccess="sameDomain" allowFullScreen="false" type="application/x-shockwave-flash" pluginspage="http://www.adobe.com/go/getflashplayer" /><br />
	</object><br />
</noscript><br />
</center><br />
<br />
Some of the features include:</p>
<ul>
<li>Progressive or instant RTMP streaming using a Flash Media Server</li>
<li>Customizable XML menu system to load multiple video files, thumbnails, video titles and descriptions</li>
<li>Dynamic Interface Options allow for turning interface elements on or off</li>
<li>Live preview of component features within the Flash interface</li>
<li>Custom color options for all aspects of the FlvPlayer interface including background colors, font colors, rollover colors, and controls for transparencies</li>
<li>Fullscreen toggle</li>
<li>Closed captions</li>
<li>Advanced video display controls including Fit To Player, Original Size, Fit to Width, and Fit to Height</li>
<li>Dynamic Buffering</li>
<li>Interface Display options that include Overlay or Outside, and Autohide</li>
<li>Dynamically rounded corners settings</li>
<li>Full API supporting all major functions as public methods</li>
<p>
For more information, please visit <a href="http://www.derekentringer.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2ZsdnBsYXllci5jb20=">FLVplayer.com</a> and <a href="http://www.derekentringer.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2RldmJhc2UuY29t">DevBase.com</a></p>
 <img src="http://www.derekentringer.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=298" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://www.derekentringer.com/blog/flv-player-flash-video-component-now-available-at-flvplayercom/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Flash Media Server Streaming Speed Testing [Part 3] &#8211; Compare Multiple Server Resources, Port Connections, Detect Upload, Download, and Latency Speed</title>
		<link>http://www.derekentringer.com/blog/flash-media-server-streaming-speed-testing-part-3-compare-multiple-server-resources-port-connections-detect-upload-download-and-latency-speed/</link>
		<comments>http://www.derekentringer.com/blog/flash-media-server-streaming-speed-testing-part-3-compare-multiple-server-resources-port-connections-detect-upload-download-and-latency-speed/#comments</comments>
		<pubDate>Tue, 12 May 2009 20:21:58 +0000</pubDate>
		<dc:creator>Derek J Entringer</dc:creator>
				<category><![CDATA[Code Samples]]></category>
		<category><![CDATA[FMS]]></category>
		<category><![CDATA[Flash]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[actionscript]]></category>
		<category><![CDATA[bandwidth]]></category>
		<category><![CDATA[detection]]></category>
		<category><![CDATA[download]]></category>
		<category><![CDATA[flash media server]]></category>
		<category><![CDATA[latency]]></category>
		<category><![CDATA[multiple]]></category>
		<category><![CDATA[port]]></category>
		<category><![CDATA[servers]]></category>
		<category><![CDATA[speed]]></category>
		<category><![CDATA[test]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[upload]]></category>

		<guid isPermaLink="false">http://www.derekentringer.com/blog/?p=218</guid>
		<description><![CDATA[
			
				
			
		

This tutorial is the final in a series of three. Part one of this tutorial outlined what is needed to detect a users upload, download, and latency between a Flash client and the Flash Media Server. Part two adds on the ability to detect which ports are available while connecting. In part three, we will be adding an external xml file that will allow you to compare connections to different Flash Media Servers in order to find which of them is the best connection for serving media. If you haven&#8217;t ...]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="clear:left; float:left; margin-top:10px; margin-bottom: 10px; margin-right:12px; margin-left:2px;">
			<a href="http://www.derekentringer.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2FwaS50d2VldG1lbWUuY29tL3NoYXJlP3VybD1odHRwJTNBJTJGJTJGd3d3LmRlcmVrZW50cmluZ2VyLmNvbSUyRmJsb2clMkZmbGFzaC1tZWRpYS1zZXJ2ZXItc3RyZWFtaW5nLXNwZWVkLXRlc3RpbmctcGFydC0zLWNvbXBhcmUtbXVsdGlwbGUtc2VydmVyLXJlc291cmNlcy1wb3J0LWNvbm5lY3Rpb25zLWRldGVjdC11cGxvYWQtZG93bmxvYWQtYW5kLWxhdGVuY3ktc3BlZWQlMkY="><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.derekentringer.com%2Fblog%2Fflash-media-server-streaming-speed-testing-part-3-compare-multiple-server-resources-port-connections-detect-upload-download-and-latency-speed%2F&amp;source=derekentringer&amp;style=normal&amp;service=TinyURL.com" height="61" width="50" /><br />
			</a>
		</div>
<p><!--PLAIN_TEXT--><br />
This tutorial is the final in a series of three. Part one of this tutorial outlined what is needed to detect a users upload, download, and latency between a Flash client and the Flash Media Server. Part two adds on the ability to detect which ports are available while connecting. In part three, we will be adding an external xml file that will allow you to compare connections to different Flash Media Servers in order to find which of them is the best connection for serving media. If you haven&#8217;t already read part one, you can find it <a href="http://www.derekentringer.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5kZXJla2VudHJpbmdlci5jb20vYmxvZy9mbGFzaC1tZWRpYS1zZXJ2ZXItc3RyZWFtaW5nLXNwZWVkLXRlc3RpbmctcGFydC0xLWRldGVjdC11cGxvYWQtZG93bmxvYWQtYW5kLWxhdGVuY3ktc3BlZWRzLw==">here</a>, and part two is available <a href="http://www.derekentringer.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5kZXJla2VudHJpbmdlci5jb20vYmxvZy9mbGFzaC1tZWRpYS1zZXJ2ZXItc3RyZWFtaW5nLXNwZWVkLXRlc3RpbmctcGFydC0yLWRldGVjdC11cGxvYWQtZG93bmxvYWQtYW5kLWxhdGVuY3ktc3BlZWRzLWFuZC1wb3J0LWNvbm5lY3Rpb24v">here</a>.</p>
<p>Again, Bandwidth detection is most important when connecting your users to the correctly compressed media to be streamed, recorded, or delivered via a Flash Media Server. This third example will walk you through the process of being able to detect a users download bandwidth, upload bandwidth, latency speeds, and the connected port between the client computer and the host server, along with iterating through multiple Flash Media Servers in an attempt to connect to the fastest and most available server. All of the code is Actionscript 2.0, and I&#8217;ve setup a Flash Media Server 3.5 to host the server side scripting. I use Influxis as my Flash Media Server host for all of these tutorials and smaller examples.</p>
<p>First, lets put together our Flash Actionscript. Here our goal is to setup our connection manager, and create a BandwidthInfo object that will call to our main.asc file (this is explained next) for sending packets to the Flash Media server to the client, and vice versa. We also will be creating an instance of our NetConnManager.as (also explained further down) which will allow the flash client to detect which port is best to connect to the Flash Server.</p>
<pre class="brush: as3;">
import NetConnManager;

var bestConn:Number;
var bestBandwidth:Number;
var connectBestConn:Number;
var whichServer:String;
var hasConnected:Boolean;
var currentlyChecking:Boolean;
var nextCheck:Number;
var upstreamsAvailable:Array = new Array();
var downstreamsAvailable:Array = new Array();
var theServers:Array;
var startTime:Number = getTimer();
var ncm:NetConnManager = new NetConnManager();
var ncmListener:Object = new Object();
var theServersXML:XML = new XML();
theServersXML.ignoreWhite = true;

ncmListener.ncConnected = function(evt:Object) {
	trace(&quot;[&quot;+Math.round(getTimer()-startTime)+&quot;ms] successfully connected using &quot;+evt.protocol+&quot;:&quot;+evt.port);
	conn_stat.text += &quot;[&quot;+Math.round(getTimer()-startTime)+&quot;ms] successfully connected using &quot;+evt.protocol+&quot;:&quot;+evt.port+newline;
};
ncmListener.ncFailedToConnect = function(evt:Object) {
	trace(&quot;failed to connect after &quot;+evt.timeout+&quot; ms&quot;);
	conn_stat.text += &quot;failed to connect after &quot;+evt.timeout+&quot; ms&quot;+newline;
};
ncm.addEventListener(&quot;ncConnected&quot;, ncmListener);
ncm.addEventListener(&quot;ncFailedToConnect&quot;, ncmListener);
ncm.connect(&quot;your.rtmphost.com&quot;, &quot;application_name&quot;);

theServersXML.load(&quot;xml/server_config.xml&quot;);
theServersXML.onLoad = function(success) {
	var index:Number = 0;
	theServers = new Array(this.firstChild.firstChild.childNodes.length);
	for (var aNode:XMLNode = this.firstChild.firstChild.firstChild; aNode != null; aNode=aNode.nextSibling) {
		theServers[index] = new Array(aNode.firstChild.childNodes.length);
		for (var subNode:XMLNode = aNode.firstChild; subNode != null; subNode=subNode.nextSibling) {
			theServers[index][subNode.nodeName] = subNode.firstChild.nodeValue;
		}
		index++;
	}
	//setup first connection
	checkConnection(theServers[0][&quot;host&quot;], theServers[0][&quot;app&quot;], 0);
};

function checkConnection(host, app, which) {

	currentlyChecking = true;

	rec_nc = new NetConnection();
	rec_nc.onStatus = function(info) {
		trace(&quot;Level: &quot;+info.level+&quot; Code: &quot;+info.code);
		if (info.code == &quot;NetConnection.Connect.Success&quot;) {
			trace(&quot;connected to: &quot;+this.uri);
			conn_stat.text += &quot;connected to: &quot;+this.uri+newline;
			startTest(rec_nc);
		} else if (info.code == &quot;NetConnection.Connect.Failed&quot; || info.code == &quot;NetConnection.Connect.Closed&quot;) {
			trace(&quot;no connection to app&quot;);
			conn_stat.text += &quot;error connection failed&quot;+newline;
		}
	};
	rec_nc.connect(&quot;rtmp://&quot;+host+&quot;/&quot;+app+&quot;/&quot;);

	function startTest(nc) {
		_global.bwInfo = new BandwidthInfo(nc);
		_global.bwInfo.start();
	}
	for (i=0; i&lt;1000; i++) {
		data += &quot;C-&gt;S&quot;;
	}
	function BandwidthInfo(nc) {
		this.nc = nc;
		this.maxLength = 10;
		this.bwInHistory = new Array(this.maxLength);
		this.bwInCtr = 0;
		this.bwOutHistory = new Array(this.maxLength);
		this.bwOutCtr = 0;
		this.pingHistory = new Array(this.maxLength);
		this.headIn = 0;
		this.headOut = 0;
		this.headPing = 0;
		this.bBWOutStop = false;
		this.bBWInStop = false;
		this.onBWInTimeout = function() {
			clearInterval(this.bwInfoTimeout);
			this.bwInfoTimeout = null;
			delete this.bwInfoTimeout;
			this.bBWInStop = true;

			if (this.bwInCtr == 0) {
				conn_stat.text += &quot;unable to receive data from server.&quot;+newline;
				this.abort(&quot;unable to receive data from server.&quot;);
				return;
			}
			this.stop();
		};
		this.onBWOutTimeout = function() {
			clearInterval(this.bwInfoTimeout);
			this.bwInfoTimeout = null;
			delete this.bwInfoTimeout;
			this.bBWOutStop = true;

			if (this.bwOutCtr == 0) {
				conn_stat.text += &quot;unable to receive data from server\n&quot;;
				this.abort(&quot;unable to send data to server\n----------\n&quot;);
				return;
			}
			trace(&quot;testing bandwidth from server&quot;);
			conn_stat.text += &quot;testing bandwidth from server&quot;+newline;
			this.bwInfoTimeout = setInterval(this, &quot;onBWInTimeout&quot;, 5*1000);
			this.serverToClient();
		};
		this.clientToServer = function() {
			this.time = getTimer();
			size = 0;
			bwinfo = this;
			this.nc.ack = function(pingVal) {
				if (!bwinfo.bBWOutStop) {
					bwinfo.bwOutHistory[bwinfo.headOut++%bwinfo.maxLength] = Math.floor(size/(getTimer()-bwinfo.time)*1000);
					bwinfo.pingHistory[bwinfo.headPing++%bwinfo.maxLength] = pingVal;
					bwinfo.nc.call(&quot;recData&quot;,0,data);
					size += 4000;
					bwinfo.bwOutCtr++;
				}
			};
			this.nc.call(&quot;recData&quot;,0,data);
			this.nc.call(&quot;recData&quot;,0,data);
		};
		this.serverToClient = function() {
			this.time = getTimer();
			size = 0;
			bwinfo = this;
			nc.onEcho = function() {
				if (!bwinfo.bBWInStop) {
					bwinfo.bwInHistory[bwinfo.headIn++%bwinfo.maxLength] = Math.floor(size/(getTimer()-bwinfo.time)*1000);
					this.call(&quot;echoData&quot;,0,0);
					size += 4000;
					bwinfo.bwInCtr++;
				}
			};
			nc.call(&quot;echoData&quot;,0,0);
			nc.call(&quot;echoData&quot;,0,0);
		};
		this.start = function() {
			conn_stat.text += &quot;testing upload speed&quot;+newline;
			trace(&quot;testing upload speed&quot;);
			clearInterval(this.bwInfoTimeout);
			this.bwInfoTimeout = null;
			delete this.bwInfoTimeout;
			this.bwInfoTimeout = setInterval(this, &quot;onBWOutTimeout&quot;, 5*1000);
			this.clientToServer();
		};
		this.stop = function() {
			this.nc = null;
			var ping_rtt = 0;
			var bw_out = 0;
			var bw_in = 0;
			for (var i = 0; i&lt;this.maxLength &amp;&amp; i&lt;this.bwOutCtr; i++) {
				ping_rtt = Math.max(ping_rtt, this.pingHistory[i]);
			}
			for (var i = 0; i&lt;this.maxLength &amp;&amp; i&lt;this.bwOutCtr; i++) {
				bw_out += this.bwOutHistory[i];
			}
			bw_out /= Math.min(this.maxLength, this.bwOutCtr);
			bw_out = Math.round((bw_out/1024)*8);
			for (var i = 0; i&lt;this.maxLength &amp;&amp; i&lt;this.bwInCtr; i++) {
				bw_in += this.bwInHistory[i];
			}
			bw_in /= Math.min(this.maxLength, this.bwInCtr);
			bw_in = Math.round((bw_in/1024)*8);

			//record
			upstreamsAvailable.push(bw_out);
			downstreamsAvailable.push(bw_in);

			var s;
			s = &quot;bandwidth results:\n&quot;;
			s += &quot;   upstream: &quot;+bw_out+&quot; kbps\n&quot;;
			s += &quot;   downstream: &quot;+bw_in+&quot; kbps\n&quot;;
			s += &quot;   latency: &quot;+ping_rtt+&quot; ms\n&quot;;
			if (ping_rtt&gt;1000) {
				s += &quot;network appears to have a very high delay\n&quot;;
			}
			if ((bw_in&gt;500) &amp;&amp; (bw_out&gt;200)) {
				s += &quot;connection supports high quality speed\n----------\n&quot;;
			} else if ((bw_in&gt;=200) &amp;&amp; (bw_out&gt;=100)) {
				s += &quot;connection supports good quality speed\n----------\n&quot;;
			} else if ((bw_in&gt;100) &amp;&amp; (bw_out&gt;80)) {
				s += &quot;connection supports mid quality speed\n----------\n&quot;;
			} else if ((bw_in&gt;20) &amp;&amp; (bw_out&gt;15)) {
				s += &quot;connection supports slow quality speed\n----------\n&quot;;
			} else {
				s += &quot;connection supports very slow quality speed\n----------\n&quot;;
			}
			trace(s);
			conn_stat.text += s+newline;
			currentlyChecking = false;
			nextCheck = which+1;
		};
		this.abort = function(reason) {
			conn_stat.text += &quot;failed &quot;+reason+newline;
			trace(&quot;failed &quot;+reason);
			currentlyChecking = false;
			nextCheck = which+1;
		};
	}

}

checkIfRunning = setInterval(this, &quot;checkConnBusy&quot;, 1000);

function checkConnBusy() {
	if (currentlyChecking == false) {
		if (nextCheck&lt;theServers.length) {
			checkConnection(theServers[nextCheck][&quot;host&quot;], theServers[nextCheck][&quot;app&quot;], nextCheck);
		} else {
			clearInterval(checkIfRunning);
			conn_stat.text += &quot;comparing connection&quot;+newline;
			compareConnections();
		}
	}
}

maxValueIndex = function (array) {
	mxm = array[0];
	for (i=0; i&lt;array.length; i++) {
		if (array[i]&gt;mxm) {
			mxm = array.index;
		}
	}
	return mxm;
};

Array.prototype.indexOf = function(value) {
	var i = 0;
	var l = this.length;
	var res = -1;
	for (i; i&lt;l; i++) {
		if (this[i] == value) {
			res = i;
			break;
		}
	}
	return res;
};

function compareConnections() {
	bestConn = maxValueIndex(upstreamsAvailable);
	bestBandwidth = maxValueIndex(upstreamsAvailable);
	connectBestConn = upstreamsAvailable.indexOf(bestConn);
	setConnectionsInterval = setInterval(this, &quot;setConnections&quot;, 500);
}
function setConnections(){
	if(theServers[connectBestConn][&quot;host&quot;] != undefined &amp;&amp; theServers[connectBestConn][&quot;app&quot;] != undefined){
		clearInterval(setConnectionsInterval);
		conn_stat.text += &quot;choosing server: rtmp://&quot;+theServers[connectBestConn][&quot;host&quot;]+&quot;/&quot;+theServers[connectBestConn][&quot;app&quot;]+newline;
	}else{
		clearInterval(setConnectionsInterval);
		conn_stat.text += &quot;connection to the server(s) has failed&quot;+newline;
	}
}
</pre>
<p>
In order to get the above to work correctly with your own Flash Media Server, you simply need to edit the following line. </p>
<pre class="brush: as3;">
ncm.connect(&quot;your.rtmphost.com&quot;, &quot;application_name&quot;);
</pre>
<p>
This is the path to the application which will hold our Main.asc file. You will also need to edit the xml/server_config.xml file in order to test against several different Flash Media Servers. This file serves as the que by which the flash client will verify and test each of the different connections, and finally pick the fastest one.</p>
<pre class="brush: xml;">
&lt;servers version=&quot;1&quot; xmlns=&quot;http://xspf.org/ns/0/&quot;&gt;
  &lt;serverList&gt;
    &lt;server&gt;
      &lt;host&gt;first_host&lt;/host&gt;
      &lt;app&gt;first_app&lt;/app&gt;
    &lt;/server&gt;
	&lt;server&gt;
      &lt;host&gt;second_host&lt;/host&gt;
      &lt;app&gt;second_app&lt;/app&gt;
    &lt;/server&gt;
  &lt;/serverList&gt;
&lt;/servers&gt;
</pre>
<p>
We now have our Flash file ready, and our servers setup within the server_config.xml.</p>
<p>Next, we want to create the server side code that will allow our final swf to call server side functions in order to return the correct upload, download, and latency values.</p>
<pre class="brush: as3;">
application.onAppStart = function (info){
	for ( i = 0; i &lt; 500; i++ ) {
		data += &quot;S-&gt;C&quot;;
	}
	Client.prototype.recData = function(data) {
		this.ping();
		var v = this.getStats();
		this.call(&quot;ack&quot;, 0, v.ping_rtt);
	}
	Client.prototype.echoData = function() {
		this.call(&quot;onEcho&quot;, 0, data);
	};
	Client.prototype.getBWInfo = function() {
		return this.getStats();
	};
	Client.prototype.onConnTimeout = function(){
		clearInterval( this.connTimeout );
		this.connTimeout = null;
		application.disconnect(this);
	}
}
application.onConnect = function(client_obj, id) {
	application.acceptConnection(client_obj);
}
</pre>
<p>
We also need our NetConnManager.as file which allows for multiple port detections.</p>
<pre class="brush: as3;">
import mx.events.EventDispatcher;
class NetConnManager extends Object {
	//EventDispatcher needs these
	var addEventListener:Function;
	var removeEventListener:Function;
	var dispatchEvent:Function;
	var dispatchQueue:Function;
	//Constants
	private var k_DEFAULTCONNLIST = [{protocol:&quot;rtmp&quot;, port:1935}, {protocol:&quot;rtmp&quot;, port:443}, {protocol:&quot;rtmpt&quot;, port:80}, {protocol:&quot;rtmps&quot;, port:443}];
	private var k_TIMEOUT:Number = 60000;
	//Variables
	private var m_connList:Array;
	private var m_serverName:String;
	private var m_appName:String;
	private var m_streamName:String;
	private var m_connListCounter:Number;
	private var m_flashComConnectTimeOut:Number;
	private var m_validNetConnection:NetConnection;
	//Constructor
	function NetConnManager() {
		EventDispatcher.initialize(this);
	}
	//Public
	//Initiates all the connection attempts.
	//Note: If no connection list is passed, the default list is used
	function connect(p_serverName:String, p_appName:String, p_connList:Array) {
		m_serverName = p_serverName;
		m_appName = p_appName;
		m_connList = (p_connList != undefined) ? p_connList : k_DEFAULTCONNLIST;
		//Set a timeout function, just in case we never connect successfully
		clearInterval(m_flashComConnectTimeOut);
		m_flashComConnectTimeOut = setInterval(this, &quot;onFlashComConnectTimeOut&quot;, k_TIMEOUT, k_TIMEOUT);
		//Creates a NetConnection for each of the protocols/ports listed in the m_connList list.
		//Connection attempts occur at intervals of 1.5 seconds. The first connection to succeed
		//will be used, all the others will be closed.
		for (var i = 0; i&lt;m_connList.length; i++) {
			this[&quot;nc&quot;+i] = new NetConnection();
			this[&quot;nc&quot;+i].owner = this;
			this[&quot;nc&quot;+i].connIndex = i;
			this[&quot;nc&quot;+i].onStatus = function(info) {
				this.pending = false;
				this.owner.m_validNetConnection = this.owner[&quot;nc&quot;+this.connIndex];
				if (info.code == &quot;NetConnection.Connect.Success&quot;) {
					clearInterval(this.owner.m_flashComConnectTimeOut);
					this.owner.dispatchEvent({type:&quot;ncConnected&quot;, nc:this.owner.m_validNetConnection, protocol:this.owner.m_connList[this.connIndex].protocol, port:this.owner.m_connList[this.connIndex].port});
					for (var i = 0; i&lt;this.owner.m_connList.length; i++) {
						if (i == this.connIndex) {
							continue;
						}
						if (this.owner[&quot;nc&quot;+i].pending) {
							clearInterval(this.owner[&quot;ncInt&quot;+i]);
							this.owner[&quot;nc&quot;+i].onStatus = null;
							this.owner[&quot;nc&quot;+i].close();
							this.owner[&quot;nc&quot;+i] = null;
							delete this.owner[&quot;nc&quot;+i];
						}
					}
				} else {
					trace(this.owner.m_connList[this.connIndex].protocol+&quot;: &quot;+this.owner.m_connList[this.connIndex].port+&quot;, onStatus: &quot;+info.code+&quot; : &quot;+info.description);
				}
			};
			this[&quot;nc&quot;+i].pending = true;
		}
		m_connListCounter = 0;
		nextConnect();
	}
	//Public
	//Returns the active connection or null if it does not exist.
	function getActiveConnection(Void):NetConnection {
		return m_validNetConnection == undefined ? null : m_validNetConnection;
	}
	function closeConnections() {
		m_validNetConnection.close();
	}
	//Private
	//Walks through the connection list to try every protocol.
	private function nextConnect(Void):Void {
		clearInterval(this[&quot;ncInt&quot;+m_connListCounter]);
		this[&quot;nc&quot;+m_connListCounter].connect(m_connList[m_connListCounter].protocol+&quot;://&quot;+m_serverName+&quot;:&quot;+m_connList[m_connListCounter].port+&quot;/&quot;+m_appName);
		if (m_connListCounter&lt;(m_connList.length-1)) {
			m_connListCounter++;
			this[&quot;ncInt&quot;+m_connListCounter] = setInterval(this, &quot;nextConnect&quot;, 1500);
		}
	}
	//Private
	//Cleans up all conenctions if none have succeeded by the timeout interval
	private function onFlashComConnectTimeOut(timeout:Number):Void {
		clearInterval(m_flashComConnectTimeOut);
		this.dispatchEvent({type:&quot;ncFailedToConnect&quot;, timeout:timeout});
		for (var i = 0; i&lt;m_connList.length; i++) {
			if (this[&quot;nc&quot;+i].pending) {
				clearInterval(this[&quot;ncInt&quot;+i]);
				this[&quot;nc&quot;+i].onStatus = null;
				this[&quot;nc&quot;+i].close();
				this[&quot;nc&quot;+i] = null;
				delete this[&quot;nc&quot;+i];
			}
		}
	}
}
</pre>
<p>
<a href="http://www.derekentringer.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5kZXJla2VudHJpbmdlci5jb20vYmFuZHdpZHRoX2V4YW1wbGVfdGhyZWUv" target=\"_blank\">Click here to see your bandwidth results</a></p>
<p><a href="http://www.derekentringer.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5kZXJla2VudHJpbmdlci5jb20vZG93bmxvYWRzL2JhbmR3aWR0aF9wYXJ0X3RocmVlLnppcA==">Download the source</a></p>
<p>This completes the tutorial series of the various methods to detect and stream media to flash clients. All three of these tutorials have built upon each other in order to provide solid methods for dynamically streaming any type of media via Flash Media Server.</p>
<p>Here are the links for this tutorial in its entirety:</p>
<p><a href="http://www.derekentringer.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5kZXJla2VudHJpbmdlci5jb20vYmxvZy9mbGFzaC1tZWRpYS1zZXJ2ZXItc3RyZWFtaW5nLXNwZWVkLXRlc3RpbmctcGFydC0xLWRldGVjdC11cGxvYWQtZG93bmxvYWQtYW5kLWxhdGVuY3ktc3BlZWRzLw==">Flash Media Server Streaming Speed Testing [Part 1] &#8211; Detect Upload, Download, and Latency Speeds</a></p>
<p><a href="http://www.derekentringer.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5kZXJla2VudHJpbmdlci5jb20vYmxvZy9mbGFzaC1tZWRpYS1zZXJ2ZXItc3RyZWFtaW5nLXNwZWVkLXRlc3RpbmctcGFydC0yLWRldGVjdC11cGxvYWQtZG93bmxvYWQtYW5kLWxhdGVuY3ktc3BlZWRzLWFuZC1wb3J0LWNvbm5lY3Rpb24v">Flash Media Server Streaming Speed Testing [Part 2] &#8211; Detect Upload, Download, and Latency Speeds, and Port Connection</a></p>
<p><a href="http://www.derekentringer.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5kZXJla2VudHJpbmdlci5jb20vYmxvZy9mbGFzaC1tZWRpYS1zZXJ2ZXItc3RyZWFtaW5nLXNwZWVkLXRlc3RpbmctcGFydC0zLWNvbXBhcmUtbXVsdGlwbGUtc2VydmVyLXJlc291cmNlcy1wb3J0LWNvbm5lY3Rpb25zLWRldGVjdC11cGxvYWQtZG93bmxvYWQtYW5kLWxhdGVuY3ktc3BlZWQv">Flash Media Server Streaming Speed Testing [Part 3] &#8211; Compare Multiple Server Resources, Port Connections, Detect Upload, Download, and Latency Speed</a></p>
 <img src="http://www.derekentringer.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=218" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://www.derekentringer.com/blog/flash-media-server-streaming-speed-testing-part-3-compare-multiple-server-resources-port-connections-detect-upload-download-and-latency-speed/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Flash Media Server Streaming Speed Testing [Part 2] &#8211; Detect Upload, Download, and Latency Speeds, and Port Connection</title>
		<link>http://www.derekentringer.com/blog/flash-media-server-streaming-speed-testing-part-2-detect-upload-download-and-latency-speeds-and-port-connection/</link>
		<comments>http://www.derekentringer.com/blog/flash-media-server-streaming-speed-testing-part-2-detect-upload-download-and-latency-speeds-and-port-connection/#comments</comments>
		<pubDate>Tue, 12 May 2009 20:20:18 +0000</pubDate>
		<dc:creator>Derek J Entringer</dc:creator>
				<category><![CDATA[Code Samples]]></category>
		<category><![CDATA[FMS]]></category>
		<category><![CDATA[Flash]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[actionscript]]></category>
		<category><![CDATA[bandwidth]]></category>
		<category><![CDATA[detection]]></category>
		<category><![CDATA[download]]></category>
		<category><![CDATA[flash media server]]></category>
		<category><![CDATA[latency]]></category>
		<category><![CDATA[port]]></category>
		<category><![CDATA[speed]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[upload]]></category>

		<guid isPermaLink="false">http://www.derekentringer.com/blog/?p=216</guid>
		<description><![CDATA[
			
				
			
		

This tutorial is the second in a series of three. Part one of this tutorial outlined what is needed to detect a users upload, download, and latency between a Flash client and the Flash Media Server. Part 2 adds on the ability to detect which ports are available while connecting.
Again, Bandwidth detection is most important when connecting your users to the correctly compressed media to be streamed, recorded, or delivered via a Flash Media Server. This second example will walk you through the process of being able to detect a ...]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="clear:left; float:left; margin-top:10px; margin-bottom: 10px; margin-right:12px; margin-left:2px;">
			<a href="http://www.derekentringer.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2FwaS50d2VldG1lbWUuY29tL3NoYXJlP3VybD1odHRwJTNBJTJGJTJGd3d3LmRlcmVrZW50cmluZ2VyLmNvbSUyRmJsb2clMkZmbGFzaC1tZWRpYS1zZXJ2ZXItc3RyZWFtaW5nLXNwZWVkLXRlc3RpbmctcGFydC0yLWRldGVjdC11cGxvYWQtZG93bmxvYWQtYW5kLWxhdGVuY3ktc3BlZWRzLWFuZC1wb3J0LWNvbm5lY3Rpb24lMkY="><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.derekentringer.com%2Fblog%2Fflash-media-server-streaming-speed-testing-part-2-detect-upload-download-and-latency-speeds-and-port-connection%2F&amp;source=derekentringer&amp;style=normal&amp;service=TinyURL.com" height="61" width="50" /><br />
			</a>
		</div>
<p><!--PLAIN_TEXT--><br />
This tutorial is the second in a series of three. Part one of this tutorial outlined what is needed to detect a users upload, download, and latency between a Flash client and the Flash Media Server. Part 2 adds on the ability to detect which ports are available while connecting.</p>
<p>Again, Bandwidth detection is most important when connecting your users to the correctly compressed media to be streamed, recorded, or delivered via a Flash Media Server. This second example will walk you through the process of being able to detect a users download bandwidth, upload bandwidth, and the latency between the client computer and the host server, along with iterating through all of the available ports that allow you to connect to the Flash Media Server. All of the code is Actionscript 2.0, and I&#8217;ve setup a Flash Media Server 3.5 to host the server side scripting. I use Influxis as my Flash Media Server host for all of these tutorials and smaller examples.</p>
<p>First, we will add our NetConnManager object which will use the NetConnManager.as exteranal Actionscript file. This is the first part of our Flash Actionscript code.</p>
<pre class="brush: as3;">
import NetConnManager;

var startTime:Number = getTimer();
var ncm:NetConnManager = new NetConnManager();
var ncmListener:Object = new Object();

ncmListener.ncConnected = function(evt:Object) {
	trace(&quot;[&quot;+Math.round(getTimer()-startTime)+&quot;ms] successfully connected using &quot;+evt.protocol+&quot;:&quot;+evt.port);
	conn_stat.text += &quot;[&quot;+Math.round(getTimer()-startTime)+&quot;ms] successfully connected using &quot;+evt.protocol+&quot;:&quot;+evt.port+newline;
};
ncmListener.ncFailedToConnect = function(evt:Object) {
	trace(&quot;failed to connect after &quot;+evt.timeout+&quot; ms&quot;);
	conn_stat.text += &quot;failed to connect after &quot;+evt.timeout+&quot; ms&quot;+newline;
};
ncm.addEventListener(&quot;ncConnected&quot;, ncmListener);
ncm.addEventListener(&quot;ncFailedToConnect&quot;, ncmListener);

ncm.connect(&quot;your.rtmphost.com&quot;, &quot;your_application_name&quot;);
</pre>
<p>In order to get the above to work correctly with your own Flash Media Server, you simply need to edit the following line.</p>
<pre class="brush: as3;">
ncm.connect(&quot;your.rtmphost.com&quot;, &quot;your_application_name&quot;);
</pre>
<p>The following code is the same as part one of this series of tutorials. If you have not read part one, you can find it <a href="http://www.derekentringer.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5kZXJla2VudHJpbmdlci5jb20vYmxvZy9mbGFzaC1tZWRpYS1zZXJ2ZXItc3RyZWFtaW5nLXNwZWVkLXRlc3RpbmctcGFydC0xLWRldGVjdC11cGxvYWQtZG93bmxvYWQtYW5kLWxhdGVuY3ktc3BlZWRzLw==">here</a>.</p>
<pre class="brush: as3;">
function connectMe() {
	rec_nc = new NetConnection();
	rec_nc.onStatus = function(info) {
		trace(&quot;Level: &quot; + info.level + &quot; Code: &quot; + info.code);
		if (info.code == &quot;NetConnection.Connect.Success&quot;) {
			trace(&quot;connected to: &quot;+this.uri);
			conn_stat.text += &quot;connected to: &quot;+this.uri+newline;
			startTest(rec_nc);
		} else if (info.code == &quot;NetConnection.Connect.Failed&quot; || info.code == &quot;NetConnection.Connect.Closed&quot;) {
			trace(&quot;no connection to app&quot;);
			conn_stat.text += &quot;error connection failed&quot;+newline;
		}
	};
	rec_nc.connect(&quot;rtmp://y9cq49zks4.rtmphost.com/bwcheck/&quot;);
}

function startTest(nc) {
	_global.bwInfo = new BandwidthInfo(nc);
	_global.bwInfo.start();
}

for (i=0; i&lt;1000; i++) {
	data += &quot;C-&gt;S&quot;;
}
function BandwidthInfo(nc) {
	this.nc = nc;
	this.maxLength = 10;
	this.bwInHistory = new Array(this.maxLength);
	this.bwInCtr = 0;
	this.bwOutHistory = new Array(this.maxLength);
	this.bwOutCtr = 0;
	this.pingHistory = new Array(this.maxLength);
	this.headIn = 0;
	this.headOut = 0;
	this.headPing = 0;
	this.bBWOutStop = false;
	this.bBWInStop = false;
	this.onBWInTimeout = function() {
		clearInterval(this.bwInfoTimeout);
		this.bwInfoTimeout = null;
		delete this.bwInfoTimeout;
		this.bBWInStop = true;

		if (this.bwInCtr == 0) {
			conn_stat.text += &quot;unable to receive data from server.&quot;+newline;
			this.abort(&quot;unable to receive data from server.&quot;);
			return;
		}

		this.stop();
	};
	this.onBWOutTimeout = function() {
		clearInterval(this.bwInfoTimeout);
		this.bwInfoTimeout = null;
		delete this.bwInfoTimeout;
		this.bBWOutStop = true;

		if (this.bwOutCtr == 0) {
			conn_stat.text += &quot;unable to receive data from server&quot;+newline;
			this.abort(&quot;unable to send data to server&quot;);
			return;
		}

		trace(&quot;testing bandwidth from server&quot;);
		conn_stat.text += &quot;testing bandwidth from server&quot;+newline;
		this.bwInfoTimeout = setInterval(this, &quot;onBWInTimeout&quot;, 5*1000);
		this.serverToClient();
	};
	this.clientToServer = function() {
		this.time = getTimer();
		size = 0;
		bwinfo = this;
		this.nc.ack = function(pingVal) {
			if (!bwinfo.bBWOutStop) {
				bwinfo.bwOutHistory[bwinfo.headOut++%bwinfo.maxLength] = Math.floor(size/(getTimer()-bwinfo.time)*1000);
				bwinfo.pingHistory[bwinfo.headPing++%bwinfo.maxLength] = pingVal;
				bwinfo.nc.call(&quot;recData&quot;, 0, data);
				size += 4000;
				bwinfo.bwOutCtr++;
			}
		};
		this.nc.call(&quot;recData&quot;, 0, data);
		this.nc.call(&quot;recData&quot;, 0, data);
	};
	this.serverToClient = function() {
		this.time = getTimer();
		size = 0;
		bwinfo = this;
		nc.onEcho = function() {
			if (!bwinfo.bBWInStop) {
				bwinfo.bwInHistory[bwinfo.headIn++%bwinfo.maxLength] = Math.floor(size/(getTimer()-bwinfo.time)*1000);
				this.call(&quot;echoData&quot;, 0, 0);
				size += 4000;
				bwinfo.bwInCtr++;
			}
		};
		nc.call(&quot;echoData&quot;, 0, 0);
		nc.call(&quot;echoData&quot;, 0, 0);
	};
	this.start = function() {
		conn_stat.text += &quot;testing upload speed&quot;+newline;
		trace(&quot;testing upload speed&quot;);
		clearInterval(this.bwInfoTimeout);
		this.bwInfoTimeout = null;
		delete this.bwInfoTimeout;
		this.bwInfoTimeout = setInterval(this, &quot;onBWOutTimeout&quot;, 5*1000);
		this.clientToServer();
	};
	this.stop = function() {
		this.nc = null;
		var ping_rtt = 0;
		var bw_out = 0;
		var bw_in = 0;
		for (var i = 0; i&lt;this.maxLength &amp;&amp; i&lt;this.bwOutCtr; i++) {
			ping_rtt = Math.max(ping_rtt, this.pingHistory[i]);
		}
		for (var i = 0; i&lt;this.maxLength &amp;&amp; i&lt;this.bwOutCtr; i++) {
			bw_out += this.bwOutHistory[i];
		}
		bw_out /= Math.min(this.maxLength, this.bwOutCtr);
		bw_out = Math.round((bw_out/1024)*8);
		for (var i = 0; i&lt;this.maxLength &amp;&amp; i&lt;this.bwInCtr; i++) {
			bw_in += this.bwInHistory[i];
		}
		bw_in /= Math.min(this.maxLength, this.bwInCtr);
		bw_in = Math.round((bw_in/1024)*8);
		var s;
		s = &quot;bandwidth results:\n&quot;;
		s += &quot;   upstream: &quot;+bw_out+&quot; kbps\n&quot;;
		s += &quot;   downstream: &quot;+bw_in+&quot; kbps\n&quot;;
		s += &quot;   latency: &quot;+ping_rtt+&quot; ms\n&quot;;
		if (ping_rtt&gt;1000) {
			s += &quot;network appears to have a very high delay\n\n&quot;;
		}
		if ((bw_in&gt;500) &amp;&amp; (bw_out&gt;200)) {
			s += &quot;connection supports high quality speed\n\n&quot;;
		} else if ((bw_in&gt;=200) &amp;&amp; (bw_out&gt;=100)) {
			s += &quot;connection supports good quality speed\n\n&quot;;
		} else if ((bw_in&gt;100) &amp;&amp; (bw_out&gt;80)) {//(bw_in&lt;250) &amp;&amp; (bw_out&lt;80) &amp;&amp;
			s += &quot;connection supports mid quality speed\n\n&quot;;
		} else if ((bw_in&gt;20) &amp;&amp; (bw_out&gt;15)) {
			s += &quot;connection supports slow quality speed\n\n&quot;;
		} else {
			s += &quot;connection supports very slow quality speed\n\n&quot;;
		}
		trace(s);
		conn_stat.text += s+newline;
	};
	this.abort = function(reason) {
		conn_stat.text += &quot;failed &quot;+reason+newline;
		trace(&quot;failed &quot;+reason);
	};
}

connectMe();
</pre>
<p>
Next, lets setup our NetConnManager.as file. This external Actionscript class allows the ncm object to iterate through all of the available ports on the Flash Media Server, and lets you know which port it has connected successfully on the server. This is useful if you are dealing with a firewall that has blocked the default port of 1935.</p>
<pre class="brush: as3;">
import mx.events.EventDispatcher;
class NetConnManager extends Object {
	//EventDispatcher needs these
	var addEventListener:Function;
	var removeEventListener:Function;
	var dispatchEvent:Function;
	var dispatchQueue:Function;
	//Constants
	private var k_DEFAULTCONNLIST = [{protocol:&quot;rtmp&quot;, port:1935}, {protocol:&quot;rtmp&quot;, port:443}, {protocol:&quot;rtmpt&quot;, port:80}, {protocol:&quot;rtmps&quot;, port:443}];
	private var k_TIMEOUT:Number = 60000;
	//Variables
	private var m_connList:Array;
	private var m_serverName:String;
	private var m_appName:String;
	private var m_streamName:String;
	private var m_connListCounter:Number;
	private var m_flashComConnectTimeOut:Number;
	private var m_validNetConnection:NetConnection;
	//Constructor
	function NetConnManager() {
		EventDispatcher.initialize(this);
	}
	//Public
	//Initiates all the connection attempts.
	//Note: If no connection list is passed, the default list is used
	function connect(p_serverName:String, p_appName:String, p_connList:Array) {
		m_serverName = p_serverName;
		m_appName = p_appName;
		m_connList = (p_connList != undefined) ? p_connList : k_DEFAULTCONNLIST;
		//Set a timeout function, just in case we never connect successfully
		clearInterval(m_flashComConnectTimeOut);
		m_flashComConnectTimeOut = setInterval(this, &quot;onFlashComConnectTimeOut&quot;, k_TIMEOUT, k_TIMEOUT);
		//Creates a NetConnection for each of the protocols/ports listed in the m_connList list.
		//Connection attempts occur at intervals of 1.5 seconds. The first connection to succeed
		//will be used, all the others will be closed.
		for (var i = 0; i&lt;m_connList.length; i++) {
			this[&quot;nc&quot;+i] = new NetConnection();
			this[&quot;nc&quot;+i].owner = this;
			this[&quot;nc&quot;+i].connIndex = i;
			this[&quot;nc&quot;+i].onStatus = function(info) {
				this.pending = false;
				this.owner.m_validNetConnection = this.owner[&quot;nc&quot;+this.connIndex];
				if (info.code == &quot;NetConnection.Connect.Success&quot;) {
					clearInterval(this.owner.m_flashComConnectTimeOut);
					this.owner.dispatchEvent({type:&quot;ncConnected&quot;, nc:this.owner.m_validNetConnection, protocol:this.owner.m_connList[this.connIndex].protocol, port:this.owner.m_connList[this.connIndex].port});
					for (var i = 0; i&lt;this.owner.m_connList.length; i++) {
						if (i == this.connIndex) {
							continue;
						}
						if (this.owner[&quot;nc&quot;+i].pending) {
							clearInterval(this.owner[&quot;ncInt&quot;+i]);
							this.owner[&quot;nc&quot;+i].onStatus = null;
							this.owner[&quot;nc&quot;+i].close();
							this.owner[&quot;nc&quot;+i] = null;
							delete this.owner[&quot;nc&quot;+i];
						}
					}
				} else {
					trace(this.owner.m_connList[this.connIndex].protocol+&quot;: &quot;+this.owner.m_connList[this.connIndex].port+&quot;, onStatus: &quot;+info.code+&quot; : &quot;+info.description);
				}
			};
			this[&quot;nc&quot;+i].pending = true;
		}
		m_connListCounter = 0;
		nextConnect();
	}
	//Public
	//Returns the active connection or null if it does not exist.
	function getActiveConnection(Void):NetConnection {
		return m_validNetConnection == undefined ? null : m_validNetConnection;
	}
	function closeConnections() {
		m_validNetConnection.close();
	}
	//Private
	//Walks through the connection list to try every protocol.
	private function nextConnect(Void):Void {
		clearInterval(this[&quot;ncInt&quot;+m_connListCounter]);
		this[&quot;nc&quot;+m_connListCounter].connect(m_connList[m_connListCounter].protocol+&quot;://&quot;+m_serverName+&quot;:&quot;+m_connList[m_connListCounter].port+&quot;/&quot;+m_appName);
		if (m_connListCounter&lt;(m_connList.length-1)) {
			m_connListCounter++;
			this[&quot;ncInt&quot;+m_connListCounter] = setInterval(this, &quot;nextConnect&quot;, 1500);
		}
	}
	//Private
	//Cleans up all conenctions if none have succeeded by the timeout interval
	private function onFlashComConnectTimeOut(timeout:Number):Void {
		clearInterval(m_flashComConnectTimeOut);
		this.dispatchEvent({type:&quot;ncFailedToConnect&quot;, timeout:timeout});
		for (var i = 0; i&lt;m_connList.length; i++) {
			if (this[&quot;nc&quot;+i].pending) {
				clearInterval(this[&quot;ncInt&quot;+i]);
				this[&quot;nc&quot;+i].onStatus = null;
				this[&quot;nc&quot;+i].close();
				this[&quot;nc&quot;+i] = null;
				delete this[&quot;nc&quot;+i];
			}
		}
	}
}
</pre>
<p>
We now have our Flash file ready, but we still need our application setup on the Flash Server. Create a new application on your Flash Media Server, and name it however you want. That application name then goes into the connect function above, along with the url for the server.</p>
<p>Next, we want to create the server side code that will allow our final swf to call server side functions in order to return the correct upload, download, and latency values.</p>
<pre class="brush: as3;">
application.onAppStart = function (info){
	for ( i = 0; i &lt; 500; i++ ) {
		data += &quot;S-&gt;C&quot;;
	}
	Client.prototype.recData = function(data) {
		this.ping();
		var v = this.getStats();
		this.call(&quot;ack&quot;, 0, v.ping_rtt);
	}
	Client.prototype.echoData = function() {
		this.call(&quot;onEcho&quot;, 0, data);
	};
	Client.prototype.getBWInfo = function() {
		return this.getStats();
	};
	Client.prototype.onConnTimeout = function(){
		clearInterval( this.connTimeout );
		this.connTimeout = null;
		application.disconnect(this);
	}
}
application.onConnect = function(client_obj, id) {
	application.acceptConnection(client_obj);
}
</pre>
<p>
And, there you have it. These scripts allow you to check the users upload and download bandwidth capabilities, check how slow the server is allowing you to connect using latency detection, and provides you with the correct port that may be available from within your current network.</p>
<p><a href="http://www.derekentringer.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5kZXJla2VudHJpbmdlci5jb20vYmFuZHdpZHRoX2V4YW1wbGVfdHdvLw==" target=\"_blank\">Click here to see your bandwidth results</a></p>
<p><a href="http://www.derekentringer.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5kZXJla2VudHJpbmdlci5jb20vZG93bmxvYWRzL2JhbmR3aWR0aF9wYXJ0X3R3by56aXA=">Download the source</a></p>
<p>Finally, be sure to have a look at my next tutorial using these same techniques. In part three, I will be adding the functionality to check multiple servers using this same code.</p>
<p>Here are the links for this tutorial in its entirety:</p>
<p><a href="http://www.derekentringer.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5kZXJla2VudHJpbmdlci5jb20vYmxvZy9mbGFzaC1tZWRpYS1zZXJ2ZXItc3RyZWFtaW5nLXNwZWVkLXRlc3RpbmctcGFydC0xLWRldGVjdC11cGxvYWQtZG93bmxvYWQtYW5kLWxhdGVuY3ktc3BlZWRzLw==">Flash Media Server Streaming Speed Testing [Part 1] &#8211; Detect Upload, Download, and Latency Speeds</a></p>
<p><a href="http://www.derekentringer.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5kZXJla2VudHJpbmdlci5jb20vYmxvZy9mbGFzaC1tZWRpYS1zZXJ2ZXItc3RyZWFtaW5nLXNwZWVkLXRlc3RpbmctcGFydC0yLWRldGVjdC11cGxvYWQtZG93bmxvYWQtYW5kLWxhdGVuY3ktc3BlZWRzLWFuZC1wb3J0LWNvbm5lY3Rpb24v">Flash Media Server Streaming Speed Testing [Part 2] &#8211; Detect Upload, Download, and Latency Speeds, and Port Connection</a></p>
<p><a href="http://www.derekentringer.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5kZXJla2VudHJpbmdlci5jb20vYmxvZy9mbGFzaC1tZWRpYS1zZXJ2ZXItc3RyZWFtaW5nLXNwZWVkLXRlc3RpbmctcGFydC0zLWNvbXBhcmUtbXVsdGlwbGUtc2VydmVyLXJlc291cmNlcy1wb3J0LWNvbm5lY3Rpb25zLWRldGVjdC11cGxvYWQtZG93bmxvYWQtYW5kLWxhdGVuY3ktc3BlZWQv">Flash Media Server Streaming Speed Testing [Part 3] &#8211; Compare Multiple Server Resources, Port Connections, Detect Upload, Download, and Latency Speed</a></p>
 <img src="http://www.derekentringer.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=216" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://www.derekentringer.com/blog/flash-media-server-streaming-speed-testing-part-2-detect-upload-download-and-latency-speeds-and-port-connection/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Flash Media Server Streaming Speed Testing [Part 1] &#8211; Detect Upload, Download, and Latency Speeds</title>
		<link>http://www.derekentringer.com/blog/flash-media-server-streaming-speed-testing-part-1-detect-upload-download-and-latency-speeds/</link>
		<comments>http://www.derekentringer.com/blog/flash-media-server-streaming-speed-testing-part-1-detect-upload-download-and-latency-speeds/#comments</comments>
		<pubDate>Tue, 12 May 2009 20:18:19 +0000</pubDate>
		<dc:creator>Derek J Entringer</dc:creator>
				<category><![CDATA[Code Samples]]></category>
		<category><![CDATA[FMS]]></category>
		<category><![CDATA[Flash]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[actionscript]]></category>
		<category><![CDATA[bandwidth]]></category>
		<category><![CDATA[detection]]></category>
		<category><![CDATA[download]]></category>
		<category><![CDATA[flash media server]]></category>
		<category><![CDATA[Influxis]]></category>
		<category><![CDATA[latency]]></category>
		<category><![CDATA[speed]]></category>
		<category><![CDATA[streaming media]]></category>
		<category><![CDATA[upload]]></category>

		<guid isPermaLink="false">http://www.derekentringer.com/blog/?p=214</guid>
		<description><![CDATA[
			
				
			
		

This tutorial is the first in a series of three that builds upon the first Flash Bandwidth &#038; Port Detection tutorial I created a while back. These three articles look to make it even easier than the original post, and go more in depth on some of the streaming options, and have better structured server side code.
If you are interested in the original article, you can find it here.
Bandwidth detection is most important when connecting your users to the correctly compressed media to be streamed, recorded, or delivered via a ...]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="clear:left; float:left; margin-top:10px; margin-bottom: 10px; margin-right:12px; margin-left:2px;">
			<a href="http://www.derekentringer.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2FwaS50d2VldG1lbWUuY29tL3NoYXJlP3VybD1odHRwJTNBJTJGJTJGd3d3LmRlcmVrZW50cmluZ2VyLmNvbSUyRmJsb2clMkZmbGFzaC1tZWRpYS1zZXJ2ZXItc3RyZWFtaW5nLXNwZWVkLXRlc3RpbmctcGFydC0xLWRldGVjdC11cGxvYWQtZG93bmxvYWQtYW5kLWxhdGVuY3ktc3BlZWRzJTJG"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.derekentringer.com%2Fblog%2Fflash-media-server-streaming-speed-testing-part-1-detect-upload-download-and-latency-speeds%2F&amp;source=derekentringer&amp;style=normal&amp;service=TinyURL.com" height="61" width="50" /><br />
			</a>
		</div>
<p><!--PLAIN_TEXT--><br />
This tutorial is the first in a series of three that builds upon the first Flash Bandwidth &#038; Port Detection tutorial I created a while back. These three articles look to make it even easier than the original post, and go more in depth on some of the streaming options, and have better structured server side code.</p>
<p>If you are interested in the original article, you can find it <a href="http://www.derekentringer.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5kZXJla2VudHJpbmdlci5jb20vYmxvZy9mbGFzaC1iYW5kd2lkdGgtcG9ydC1kZXRlY3Rpb24v">here</a>.</p>
<p>Bandwidth detection is most important when connecting your users to the correctly compressed media to be streamed, recorded, or delivered via a Flash Media Server. This example will walk you through the process of being able to detect a users download bandwidth, upload bandwidth, and the latency between the client computer and the host server. All of the code is Actionscript 2.0, and I&#8217;ve setup a Flash Media Server 3.5 to host the server side scripting. I use Influxis as my Flash Media Server host for all of these tutorials and smaller examples.</p>
<p>Now, onto the code.</p>
<p>First, lets put together our Flash Actionscript. Here our goal is to setup our connection manager, and create a BandwidthInfo object that will call to our main.asc file (this is explained next) for sending packets to the Flash Media server to the client, and vice versa.</p>
<pre class="brush: as3;">
function connectMe() {
	rec_nc = new NetConnection();
	rec_nc.onStatus = function(info) {
		trace(&quot;Level: &quot; + info.level + &quot; Code: &quot; + info.code);
		if (info.code == &quot;NetConnection.Connect.Success&quot;) {
			trace(&quot;connected to: &quot;+this.uri);
			conn_stat.text += &quot;connected to: &quot;+this.uri+newline;
			startTest(rec_nc);
		} else if (info.code == &quot;NetConnection.Connect.Failed&quot; || info.code == &quot;NetConnection.Connect.Closed&quot;) {
			trace(&quot;no connection to app&quot;);
			conn_stat.text += &quot;error connection failed&quot;+newline;
		}
	};
	rec_nc.connect(&quot;rtmp://your.host.com/application_name/&quot;);
}

function startTest(nc) {
	_global.bwInfo = new BandwidthInfo(nc);
	_global.bwInfo.start();
}

for (i=0; i&lt;1000; i++) {
	data += &quot;C-&gt;S&quot;;
}
function BandwidthInfo(nc) {
	this.nc = nc;
	this.maxLength = 10;
	this.bwInHistory = new Array(this.maxLength);
	this.bwInCtr = 0;
	this.bwOutHistory = new Array(this.maxLength);
	this.bwOutCtr = 0;
	this.pingHistory = new Array(this.maxLength);
	this.headIn = 0;
	this.headOut = 0;
	this.headPing = 0;
	this.bBWOutStop = false;
	this.bBWInStop = false;
	this.onBWInTimeout = function() {
		clearInterval(this.bwInfoTimeout);
		this.bwInfoTimeout = null;
		delete this.bwInfoTimeout;
		this.bBWInStop = true;

		if (this.bwInCtr == 0) {
			conn_stat.text += &quot;unable to receive data from server.&quot;+newline;
			this.abort(&quot;unable to receive data from server.&quot;);
			return;
		}

		this.stop();
	};
	this.onBWOutTimeout = function() {
		clearInterval(this.bwInfoTimeout);
		this.bwInfoTimeout = null;
		delete this.bwInfoTimeout;
		this.bBWOutStop = true;

		if (this.bwOutCtr == 0) {
			conn_stat.text += &quot;unable to receive data from server&quot;+newline;
			this.abort(&quot;unable to send data to server&quot;);
			return;
		}

		trace(&quot;testing bandwidth from server&quot;);
		conn_stat.text += &quot;testing bandwidth from server&quot;+newline;
		this.bwInfoTimeout = setInterval(this, &quot;onBWInTimeout&quot;, 5*1000);
		this.serverToClient();
	};
	this.clientToServer = function() {
		this.time = getTimer();
		size = 0;
		bwinfo = this;
		this.nc.ack = function(pingVal) {
			if (!bwinfo.bBWOutStop) {
				bwinfo.bwOutHistory[bwinfo.headOut++%bwinfo.maxLength] = Math.floor(size/(getTimer()-bwinfo.time)*1000);
				bwinfo.pingHistory[bwinfo.headPing++%bwinfo.maxLength] = pingVal;
				bwinfo.nc.call(&quot;recData&quot;, 0, data);
				size += 4000;
				bwinfo.bwOutCtr++;
			}
		};
		this.nc.call(&quot;recData&quot;, 0, data);
		this.nc.call(&quot;recData&quot;, 0, data);
	};
	this.serverToClient = function() {
		this.time = getTimer();
		size = 0;
		bwinfo = this;
		nc.onEcho = function() {
			if (!bwinfo.bBWInStop) {
				bwinfo.bwInHistory[bwinfo.headIn++%bwinfo.maxLength] = Math.floor(size/(getTimer()-bwinfo.time)*1000);
				this.call(&quot;echoData&quot;, 0, 0);
				size += 4000;
				bwinfo.bwInCtr++;
			}
		};
		nc.call(&quot;echoData&quot;, 0, 0);
		nc.call(&quot;echoData&quot;, 0, 0);
	};
	this.start = function() {
		conn_stat.text += &quot;testing upload speed&quot;+newline;
		trace(&quot;testing upload speed&quot;);
		clearInterval(this.bwInfoTimeout);
		this.bwInfoTimeout = null;
		delete this.bwInfoTimeout;
		this.bwInfoTimeout = setInterval(this, &quot;onBWOutTimeout&quot;, 5*1000);
		this.clientToServer();
	};
	this.stop = function() {
		this.nc = null;
		var ping_rtt = 0;
		var bw_out = 0;
		var bw_in = 0;
		for (var i = 0; i&lt;this.maxLength &amp;&amp; i&lt;this.bwOutCtr; i++) {
			ping_rtt = Math.max(ping_rtt, this.pingHistory[i]);
		}
		for (var i = 0; i&lt;this.maxLength &amp;&amp; i&lt;this.bwOutCtr; i++) {
			bw_out += this.bwOutHistory[i];
		}
		bw_out /= Math.min(this.maxLength, this.bwOutCtr);
		bw_out = Math.round((bw_out/1024)*8);
		for (var i = 0; i&lt;this.maxLength &amp;&amp; i&lt;this.bwInCtr; i++) {
			bw_in += this.bwInHistory[i];
		}
		bw_in /= Math.min(this.maxLength, this.bwInCtr);
		bw_in = Math.round((bw_in/1024)*8);
		var s;
		s += &quot;bandwidth\n&quot;;
		s += &quot;   upstream: &quot;+bw_out+&quot; kbps\n&quot;;
		s += &quot;   downstream: &quot;+bw_in+&quot; kbps\n&quot;;
		s += &quot;   latency: &quot;+ping_rtt+&quot; ms\n&quot;;
		if (ping_rtt&gt;1000) {
			s += &quot;network appears to have a very high delay\n\n&quot;;
		}
		if ((bw_in&gt;500) &amp;&amp; (bw_out&gt;200)) {
			s += &quot;connection supports high quality speed\n\n&quot;;
		} else if ((bw_in&gt;=200) &amp;&amp; (bw_out&gt;=100)) {
			s += &quot;connection supports good quality speed\n\n&quot;;
		} else if ((bw_in&gt;100) &amp;&amp; (bw_out&gt;80)) {//(bw_in&lt;250) &amp;&amp; (bw_out&lt;80) &amp;&amp;
			s += &quot;connection supports mid quality speed\n\n&quot;;
		} else if ((bw_in&gt;20) &amp;&amp; (bw_out&gt;15)) {
			s += &quot;connection supports slow quality speed\n\n&quot;;
		} else {
			s += &quot;connection supports very slow quality speed\n\n&quot;;
		}
		trace(s);
		conn_stat.text += s+newline;
	};
	this.abort = function(reason) {
		conn_stat.text += &quot;failed &quot;+reason+newline;
		trace(&quot;failed &quot;+reason);
	};
}

connectMe();
</pre>
<p>
In order to get the above to work correctly with your own Flash Media Server, you simply need to edit the following line.</p>
<pre class="brush: as3;">
rec_nc.connect(&quot;rtmp://your.host.com/application_name/&quot;);
</pre>
<p>
We now have our Flash file ready, but we still need our application setup on the Flash Server. Create a new application on your Flash Media Server, and name it however you want. That application name then goes into the connect function above, along with the url for the server.</p>
<p>Next, we want to create the server side code that will allow our final swf to call server side functions in order to return the correct upload, download, and latency values.</p>
<pre class="brush: as3;">
application.onAppStart = function (info){
	for ( i = 0; i &lt; 500; i++ ) {
		data += &quot;S-&gt;C&quot;;
	}
	Client.prototype.recData = function(data) {
		this.ping();
		var v = this.getStats();
		this.call(&quot;ack&quot;, 0, v.ping_rtt);
	}
	Client.prototype.echoData = function() {
		this.call(&quot;onEcho&quot;, 0, data);
	};
	Client.prototype.getBWInfo = function() {
		return this.getStats();
	};
	Client.prototype.onConnTimeout = function(){
		clearInterval( this.connTimeout );
		this.connTimeout = null;
		application.disconnect(this);
	}
}
application.onConnect = function(client_obj, id) {
	application.acceptConnection(client_obj);
}
</pre>
<p>
<a href="http://www.derekentringer.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5kZXJla2VudHJpbmdlci5jb20vYmFuZHdpZHRoX2V4YW1wbGVfb25lLw==" target=\"_blank\">Click here to see your bandwidth results</a></p>
<p><a href="http://www.derekentringer.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5kZXJla2VudHJpbmdlci5jb20vZG93bmxvYWRzL2JhbmR3aWR0aF9wYXJ0X29uZS56aXA=">Download the source</a></p>
<p>Next, take a look at how you can use the above code along with Port Detection to be sure that your users can connect to your Flash Media Server applications from behind certain firewall setting in the <a href="http://www.derekentringer.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5kZXJla2VudHJpbmdlci5jb20vYmxvZy9iYW5kd2lkdGgtdXBsb2FkLWRvd25sb2FkLWxhdGVuY3ktc3BlZWQtYW5kLXBvcnQtZGV0ZWN0aW9uLXBhcnQtMg==">part two</a> of this three part tutorial series.</p>
<p>Here are the links for this tutorial in its entirety:</p>
<p><a href="http://www.derekentringer.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5kZXJla2VudHJpbmdlci5jb20vYmxvZy9mbGFzaC1tZWRpYS1zZXJ2ZXItc3RyZWFtaW5nLXNwZWVkLXRlc3RpbmctcGFydC0xLWRldGVjdC11cGxvYWQtZG93bmxvYWQtYW5kLWxhdGVuY3ktc3BlZWRzLw==">Flash Media Server Streaming Speed Testing [Part 1] &#8211; Detect Upload, Download, and Latency Speeds</a></p>
<p><a href="http://www.derekentringer.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5kZXJla2VudHJpbmdlci5jb20vYmxvZy9mbGFzaC1tZWRpYS1zZXJ2ZXItc3RyZWFtaW5nLXNwZWVkLXRlc3RpbmctcGFydC0yLWRldGVjdC11cGxvYWQtZG93bmxvYWQtYW5kLWxhdGVuY3ktc3BlZWRzLWFuZC1wb3J0LWNvbm5lY3Rpb24v">Flash Media Server Streaming Speed Testing [Part 2] &#8211; Detect Upload, Download, and Latency Speeds, and Port Connection</a></p>
<p><a href="http://www.derekentringer.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5kZXJla2VudHJpbmdlci5jb20vYmxvZy9mbGFzaC1tZWRpYS1zZXJ2ZXItc3RyZWFtaW5nLXNwZWVkLXRlc3RpbmctcGFydC0zLWNvbXBhcmUtbXVsdGlwbGUtc2VydmVyLXJlc291cmNlcy1wb3J0LWNvbm5lY3Rpb25zLWRldGVjdC11cGxvYWQtZG93bmxvYWQtYW5kLWxhdGVuY3ktc3BlZWQv">Flash Media Server Streaming Speed Testing [Part 3] &#8211; Compare Multiple Server Resources, Port Connections, Detect Upload, Download, and Latency Speed</a></p>
 <img src="http://www.derekentringer.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=214" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://www.derekentringer.com/blog/flash-media-server-streaming-speed-testing-part-1-detect-upload-download-and-latency-speeds/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Stratus &#8211; P2P Communication Using RTMFP and Flash 10</title>
		<link>http://www.derekentringer.com/blog/stratus-p2p-communication-using-rtmfp-and-flash-10/</link>
		<comments>http://www.derekentringer.com/blog/stratus-p2p-communication-using-rtmfp-and-flash-10/#comments</comments>
		<pubDate>Wed, 22 Apr 2009 15:14:20 +0000</pubDate>
		<dc:creator>Derek J Entringer</dc:creator>
				<category><![CDATA[FMS]]></category>
		<category><![CDATA[Flash]]></category>
		<category><![CDATA[Flex]]></category>
		<category><![CDATA[PHP/MySQL]]></category>
		<category><![CDATA[actionscript]]></category>
		<category><![CDATA[adobe]]></category>
		<category><![CDATA[communication]]></category>
		<category><![CDATA[flash 10]]></category>
		<category><![CDATA[p2p]]></category>
		<category><![CDATA[RTMFP]]></category>
		<category><![CDATA[RTMP]]></category>
		<category><![CDATA[stratus]]></category>

		<guid isPermaLink="false">http://www.derekentringer.com/blog/?p=200</guid>
		<description><![CDATA[
			
				
			
		

After doing some research on live broadcasting events using streaming video, I happened to come across a beta Adobe product called Stratus which builds upon Adobe&#8217;s RTMP. Not to confuse RTMP (Real Time Media Protocol) with RTMFP (Real Time Media Flow Protocol), RTMFP is a new communication protocol built by Adobe that will let users connect and communicate using P2P between multiple clients running a Flash or Adobe AIR application.
Stratus as defined by Adobe&#8230;
Stratus is a hosted rendezvous service that aids in establishing communications between Flash Players or Adobe AIR ...]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="clear:left; float:left; margin-top:10px; margin-bottom: 10px; margin-right:12px; margin-left:2px;">
			<a href="http://www.derekentringer.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2FwaS50d2VldG1lbWUuY29tL3NoYXJlP3VybD1odHRwJTNBJTJGJTJGd3d3LmRlcmVrZW50cmluZ2VyLmNvbSUyRmJsb2clMkZzdHJhdHVzLXAycC1jb21tdW5pY2F0aW9uLXVzaW5nLXJ0bWZwLWFuZC1mbGFzaC0xMCUyRg=="><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.derekentringer.com%2Fblog%2Fstratus-p2p-communication-using-rtmfp-and-flash-10%2F&amp;source=derekentringer&amp;style=normal&amp;service=TinyURL.com" height="61" width="50" /><br />
			</a>
		</div>
<p><!--PLAIN_TEXT--><br />
After doing some research on live broadcasting events using streaming video, I happened to come across a beta Adobe product called Stratus which builds upon Adobe&#8217;s RTMP. Not to confuse RTMP (Real Time Media Protocol) with RTMFP (Real Time Media Flow Protocol), RTMFP is a new communication protocol built by Adobe that will let users connect and communicate using P2P between multiple clients running a Flash or Adobe AIR application.</p>
<p>Stratus as defined by Adobe&#8230;</p>
<p><em>Stratus is a hosted rendezvous service that aids in establishing communications between Flash Players or Adobe AIR endpoints using RTMFP. Flash Player endpoints must stay connected to the server during the entire time of communications. Unlike Flash Media Server, Stratus does not stream video or support media relay, shared objects, or scripting. Stratus is being made available as a beta service through Adobe Labs to allow our developer community to begin building applications using RTMFP.</em></p>
<p>&#8230;which basically states that Stratus can be used in combination with Flash Media Server to allow for developers to easily connect a small amount of users (at the moment) directly instead of through the Flash Media Server using peer-to-peer technology.</p>
<p><img src="http://derekentringer.com/img/stratus_voip.jpg" /></p>
<p>Flash Media Server is built to support client to server communication. Stratus breaks free of that structure and allows client to client communication. This is a great starting point for Flash and P2P application development.</p>
<p>Unfortunately, this system was not intended to create an infinitely scalable MMORPG, although, there are some variables within the Stratus environment that will allow you to push the user limit over the default of 5.</p>
<p>Adobe&#8217;s first iteration of RTMFP is really only a taste of what is to come, and is only a glimpse into the Flash world of P2P.</p>
<p>Here are some tutorial resources I&#8217;ve put together. Feel free to leave any that you have also found helpful in learning how to effectively use Stratus.</p>
<p><a href="http://www.derekentringer.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2xhYnMuYWRvYmUuY29tL3RlY2hub2xvZ2llcy9zdHJhdHVzLw==">Stratus Home Page</a><br />
<a href="http://www.derekentringer.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cHM6Ly93d3cuYWRvYmUuY29tL2NmdXNpb24vZW50aXRsZW1lbnQvaW5kZXguY2ZtP2U9c3RyYXR1cw==">Get A Stratus Developer Key</a><br />
<a href="http://www.derekentringer.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2xhYnMuYWRvYmUuY29tL3dpa2kvaW5kZXgucGhwL1N0cmF0dXM6RkFR">Adobe Labs Stratus FAQ</a><br />
<a href="http://www.derekentringer.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2xhYnMuYWRvYmUuY29tL3RlY2hub2xvZ2llcy9zdHJhdHVzL3NhbXBsZXMv">Adobe Labs Stratus Sample Application w/source</a><br />
<a href="http://www.derekentringer.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2xhYnMuaW5mbHV4aXMuY29tLz9wPTg2">Tutorial and Downloadable Files from Influxis.com</a><br />
<a href="http://www.derekentringer.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2FjdGl2ZTYuY29tL2Jsb2cvZmxleC90aGUtYWRvYmUtc3RyYXR1cy1iZXRhLXNhbXBsZS1hcHAtYW5kLXBocG15c3FsLw==">Stratus Application Using PHP/MySQL</a><br />
<a href="http://www.derekentringer.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL21hcmNiYy5ibG9nc3BvdC5jb20vMjAwOS8wMy9maWxlLXNoYXJpbmctdXNpbmctc3RyYXR1cy1wYXJ0LTItc2VuZC5odG1s">Stratus, Python, and File Sharing</a><br />
<a href="http://www.derekentringer.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5hZG9iZS5jb20vZGV2bmV0L2ZsYXNocGxheWVyL2FydGljbGVzL3J0bWZwX3N0cmF0dXNfYXBwLmh0bWw=">Stratus Basics</a></p>
 <img src="http://www.derekentringer.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=200" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://www.derekentringer.com/blog/stratus-p2p-communication-using-rtmfp-and-flash-10/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Flash Bandwidth &amp; Port Detection</title>
		<link>http://www.derekentringer.com/blog/flash-bandwidth-port-detection/</link>
		<comments>http://www.derekentringer.com/blog/flash-bandwidth-port-detection/#comments</comments>
		<pubDate>Wed, 29 Oct 2008 18:42:16 +0000</pubDate>
		<dc:creator>Derek J Entringer</dc:creator>
				<category><![CDATA[Code Samples]]></category>
		<category><![CDATA[FMS]]></category>
		<category><![CDATA[Flash]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[1935]]></category>
		<category><![CDATA[443]]></category>
		<category><![CDATA[80]]></category>
		<category><![CDATA[actionscript]]></category>
		<category><![CDATA[bandwidth]]></category>
		<category><![CDATA[calculate]]></category>
		<category><![CDATA[check]]></category>
		<category><![CDATA[detection]]></category>
		<category><![CDATA[flash media server]]></category>
		<category><![CDATA[netConnection]]></category>
		<category><![CDATA[port]]></category>
		<category><![CDATA[RTMP]]></category>
		<category><![CDATA[rtmps]]></category>
		<category><![CDATA[rtmpt]]></category>
		<category><![CDATA[test]]></category>

		<guid isPermaLink="false">http://derekentringer.com/blog/?p=118</guid>
		<description><![CDATA[
			
				
			
		

Being able to detect a users bandwidth can be an important part of serving them streaming video. Using their bandwidth you can stream a video that will play well using their connection speeds.
The first step is to create our NetConnection.as file. This is used by our bandwidth checking script to connect to our Flash Media Server via RTMP, select an available port, and talk with our bw_check.asc to report the users available bandwidth.

import mx.events.EventDispatcher;
class NCManager extends Object {
	// EventDispatcher needs these
	var addEventListener:Function;
	var removeEventListener:Function;
	var dispatchEvent:Function;
	var dispatchQueue:Function;
	// Constants
	private var k_DEFAULTCONNLIST = [{protocol:&#34;rtmp&#34;, ...]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="clear:left; float:left; margin-top:10px; margin-bottom: 10px; margin-right:12px; margin-left:2px;">
			<a href="http://www.derekentringer.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2FwaS50d2VldG1lbWUuY29tL3NoYXJlP3VybD1odHRwJTNBJTJGJTJGd3d3LmRlcmVrZW50cmluZ2VyLmNvbSUyRmJsb2clMkZmbGFzaC1iYW5kd2lkdGgtcG9ydC1kZXRlY3Rpb24lMkY="><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.derekentringer.com%2Fblog%2Fflash-bandwidth-port-detection%2F&amp;source=derekentringer&amp;style=normal&amp;service=TinyURL.com" height="61" width="50" /><br />
			</a>
		</div>
<p><!--PLAIN_TEXT--><br />
Being able to detect a users bandwidth can be an important part of serving them streaming video. Using their bandwidth you can stream a video that will play well using their connection speeds.</p>
<p>The first step is to create our NetConnection.as file. This is used by our bandwidth checking script to connect to our Flash Media Server via RTMP, select an available port, and talk with our bw_check.asc to report the users available bandwidth.</p>
<pre class="brush: as3;">
import mx.events.EventDispatcher;
class NCManager extends Object {
	// EventDispatcher needs these
	var addEventListener:Function;
	var removeEventListener:Function;
	var dispatchEvent:Function;
	var dispatchQueue:Function;
	// Constants
	private var k_DEFAULTCONNLIST = [{protocol:&quot;rtmp&quot;, port:1935}, {protocol:&quot;rtmp&quot;, port:443}, {protocol:&quot;rtmpt&quot;, port:80}, {protocol:&quot;rtmps&quot;, port:443}];
	private var k_TIMEOUT:Number = 60000;
	// Variables
	private var m_connList:Array;
	private var m_serverName:String;
	private var m_appName:String;
	private var m_streamName:String;
	private var m_connListCounter:Number;
	private var m_flashComConnectTimeOut:Number;
	private var m_validNetConnection:NetConnection;
	// Constructor
	function NCManager() {
		trace(&quot;NCManager initialized&quot;);
		EventDispatcher.initialize(this);
	}
	// Public
	// Initiates all the connection attempts.
	// Note: If no connection list is passed, the default list is used
	function connect(p_serverName:String, p_appName:String, p_connList:Array) {
		m_serverName = p_serverName;
		m_appName = p_appName;
		m_connList = (p_connList != undefined) ? p_connList : k_DEFAULTCONNLIST;
		// Set a timeout function, just in case we never connect successfully
		clearInterval(m_flashComConnectTimeOut);
		m_flashComConnectTimeOut = setInterval(this, &quot;onFlashComConnectTimeOut&quot;, k_TIMEOUT, k_TIMEOUT);
		// Creates a NetConnection for each of the protocols/ports listed in the m_connList list.
		// Connection attempts occur at intervals of 1.5 seconds. The first connection to succeed
		// will be used, all the others will be closed.
		for (var i = 0; i&lt;m_connList.length; i++) {
			this[&quot;nc&quot;+i] = new NetConnection();
			this[&quot;nc&quot;+i].owner = this;
			this[&quot;nc&quot;+i].connIndex = i;
			this[&quot;nc&quot;+i].onBWDone = function(p_bw) {
				this.owner.dispatchEvent({type:&quot;ncBandWidth&quot;, kbps:p_bw});
			};
			this[&quot;nc&quot;+i].onBWCheck = function(counter) {
				return ++counter;
			};
			this[&quot;nc&quot;+i].onStatus = function(info) {
				this.pending = false;
				this.owner.m_validNetConnection = this.owner[&quot;nc&quot;+this.connIndex];
				if (info.code == &quot;NetConnection.Connect.Success&quot;) {
					// We have a successfull connection
					clearInterval(this.owner.m_flashComConnectTimeOut);
					this.owner.dispatchEvent({type:&quot;ncConnected&quot;, nc:this.owner.m_validNetConnection, protocol:this.owner.m_connList[this.connIndex].protocol, port:this.owner.m_connList[this.connIndex].port});
					for (var i = 0; i&lt;this.owner.m_connList.length; i++) {
						if (i == this.connIndex) {
							continue;
						}
						if (this.owner[&quot;nc&quot;+i].pending) {
							clearInterval(this.owner[&quot;ncInt&quot;+i]);
							this.owner[&quot;nc&quot;+i].onStatus = null;
							this.owner[&quot;nc&quot;+i].close();
							this.owner[&quot;nc&quot;+i] = null;
							delete this.owner[&quot;nc&quot;+i];
						}
					}
				} else {
					trace(this.owner.m_connList[this.connIndex].protocol+&quot;: &quot;+this.owner.m_connList[this.connIndex].port+&quot;, onStatus: &quot;+info.code+&quot; : &quot;+info.description);
				}
			};
			this[&quot;nc&quot;+i].pending = true;
		}
		m_connListCounter = 0;
		nextConnect();
	}
	// Public
	// Returns the stream length for a given stream name.
	// Note: requires matching server function to be present on the server.
	function getStreamLength(streamName:String) {
		var res = new Object();
		res.owner = this;
		res.name = streamName;
		res.onResult = function(p_length) {
			this.owner.dispatchEvent({type:&quot;ncStreamLength&quot;, length:p_length, name:res.name});
		};
		m_validNetConnection.call(&quot;getStreamLength&quot;,res,streamName);
	}
	// Public
	// Calls a server-side function to initiate a bandwdith check.
	// Note: requires matching server function to be present on the server.
	function getBandWidth(Void):Void {
		m_validNetConnection.call(&quot;checkBandwidth&quot;,null);
	}
	// Public
	// Returns the active connection or null if it does not exist.
	function getActiveConnection(Void):NetConnection {
		trace(m_validNetConnection == undefined ? null : m_validNetConnection);
		return m_validNetConnection == undefined ? null : m_validNetConnection;
	}
	function closeConnections() {
		trace(&quot;CLOSING= &quot;+m_validNetConnection);
		m_validNetConnection.close();
	}
	// Private
	// Walks through the connection list to try every protocol.
	private function nextConnect(Void):Void {
		clearInterval(this[&quot;ncInt&quot;+m_connListCounter]);
		this[&quot;nc&quot;+m_connListCounter].connect(m_connList[m_connListCounter].protocol+&quot;://&quot;+m_serverName+&quot;:&quot;+m_connList[m_connListCounter].port+&quot;/&quot;+m_appName);
		if (m_connListCounter&lt;(m_connList.length-1)) {
			m_connListCounter++;
			this[&quot;ncInt&quot;+m_connListCounter] = setInterval(this, &quot;nextConnect&quot;, 1500);
		}
	}
	// Private
	// Cleans up all conenctions if none have succeeded by the timeout interval
	private function onFlashComConnectTimeOut(timeout:Number):Void {
		clearInterval(m_flashComConnectTimeOut);
		this.dispatchEvent({type:&quot;ncFailedToConnect&quot;, timeout:timeout});
		for (var i = 0; i&lt;m_connList.length; i++) {
			if (this[&quot;nc&quot;+i].pending) {
				clearInterval(this[&quot;ncInt&quot;+i]);
				this[&quot;nc&quot;+i].onStatus = null;
				this[&quot;nc&quot;+i].close();
				this[&quot;nc&quot;+i] = null;
				delete this[&quot;nc&quot;+i];
			}
		}
	}
}
</pre>
<p>The second step is to create our FMS server side code. The bwcheck.asc file sends packets at a size of about 16Kb from the FMS and calculates the response latency over the users network.</p>
<pre class="brush: as3;">
application.onConnect = function(p_client, p_autoSenseBW) {
	this.acceptConnection(p_client);
	if (p_autoSenseBW)
		this.calculateClientBw(p_client);
	else
		p_client.call(&quot;onBWDone&quot;);
}
Client.prototype.getStreamLength = function(p_streamName) {
	return Stream.length(p_streamName);
}
Client.prototype.checkBandwidth = function() {
	application.calculateClientBw(this);
}
application.calculateClientBw = function(p_client) {
	p_client.payload = new Array();
	for (var i=0; i&lt;1200; i++){
		p_client.payload[i] = Math.random();//16K approx
	}
	var res = new Object();
	res.latency = 0;
	res.cumLatency = 1;
	res.bwTime = 0;
	res.count = 0;
	res.sent = 0;
	res.client = p_client;
	var stats = p_client.getStats();
	var now = (new Date()).getTime()/1;
	res.pakSent = new Array();
	res.pakRecv = new Array();
	res.beginningValues = {b_down:stats.bytes_out, b_up:stats.bytes_in, time:now};
	res.onResult = function(p_val) {
		var now = (new Date()).getTime()/1;
		this.pakRecv[this.count] = now;
		this.count++;
		var timePassed = (now - this.beginningValues.time);
		if (this.count == 1) {
			this.latency = Math.min(timePassed, 800);
			this.latency = Math.max(this.latency, 10);
		}
		if ( this.count == 2 &amp;&amp; (timePassed&lt;2000)) {
			this.pakSent[res.sent++] = now;
			this.cumLatency++;
			this.client.call(&quot;onBWCheck&quot;, res, this.client.payload);
		} else if ( this.sent == this.count ) {
			//see if we need to normalize latency
			if ( this.latency &gt;= 100 ) {
				if (  this.pakRecv[1] - this.pakRecv[0] &gt; 1000 ) {
					this.latency = 100;
				}
			}
			delete this.client.payload;
			//got back responses for all the packets compute the bandwidth
			var stats = this.client.getStats();
			var deltaDown = (stats.bytes_out - this.beginningValues.b_down)*8/1000;
			var deltaTime = ((now - this.beginningValues.time) - (this.latency * this.cumLatency) )/1000;
			if ( deltaTime &lt;= 0 )
				deltaTime = (now - this.beginningValues.time)/1000;

			var kbitDown = Math.round(deltaDown/deltaTime);
			trace(&quot;onBWDone: kbitDown = &quot; + kbitDown + &quot;, deltaDown= &quot; + deltaDown + &quot;, deltaTime = &quot; + deltaTime + &quot;, latency = &quot; + this.latency + &quot;KBytes &quot; + (stats.bytes_out - this.beginningValues.b_down)/1024) ;
			this.client.call(&quot;onBWDone&quot;, null, kbitDown,  deltaDown, deltaTime, this.latency );
		}
	}
	res.pakSent[res.sent++] = now;
	p_client.call(&quot;onBWCheck&quot;, res, &quot;&quot;);
	res.pakSent[res.sent++] = now;
	p_client.call(&quot;onBWCheck&quot;, res, p_client.payload);
}
</pre>
<p>Third step. Bring everything together within our flash file, and print our results to text fields on the stage.</p>
<pre class="brush: as3;">
stop();

import NCManager;

var ns:NetStream;
var fileName:String;
var k_STARTTIME:Number = getTimer();

//server info
var k_SERVERNAME:String = &quot;server_name&quot;;
var k_APPNAME:String = &quot;application_folder_name&quot;;
var k_ASC_PATH:String = &quot;rtmp://&quot;+k_SERVERNAME+&quot;/&quot;+k_APPNAME+&quot;/bwcheck.asc&quot;;

nc = new NetConnection();
nc.connect(k_ASC_PATH,true);
nc.onStatus = function(info) {
	trace(&quot;Level: &quot;+info.level+&quot; Code: &quot;+info.code);
	if (info.code == &quot;NetConnection.Connect.Success&quot;) {
		trace(&quot;loaded: &quot;+this.uri);
	}
};

//the variable p_bw returned by bwcheck.asc holds a value equal to the detected download speed in kilobits per second
//for best results we should serve video that is encoded at a rate less than or equal to kbitsDown
NetConnection.prototype.onBWDone = function(p_bw) {
	trace(&quot;BANDWIDTH= &quot;+p_bw);
	bandwidth.text = &quot;Bandwidth= &quot;+p_bw
	//close the Netconnection to bwcheck
	this.close();
};

NetConnection.prototype.onBWCheck = function() {
	return ++counter;
};

var ncm:NCManager = new NCManager();
var ncmListener:Object = new Object();

//fires when it has found a successfull connection
ncmListener.ncConnected = function(evt:Object) {
	trace(&quot;[&quot;+Math.round(getTimer()-k_STARTTIME)+&quot;ms] Successfully connected using &quot;+evt.protocol+&quot;:&quot;+evt.port);
	port.text = &quot;connected using &quot;+evt.protocol+&quot;:&quot;+evt.port
};

//fires when it has timed-out trying to find a good connection
ncmListener.ncFailedToConnect = function(evt:Object) {
	trace(&quot;Failed to connect after &quot;+evt.timeout+&quot; milliseconds.&quot;);
};

//fires when streamlength has been detected
ncmListener.ncStreamLength = function(evt:Object) {
	trace(&quot;[&quot;+Math.round(getTimer()-k_STARTTIME)+&quot;ms] Streamlength of &quot;+evt.name+&quot; is &quot;+evt.length+&quot; seconds.&quot;);
};

//set listeners on the NCM instance
ncm.addEventListener(&quot;ncConnected&quot;,ncmListener);
ncm.addEventListener(&quot;ncFailedToConnect&quot;,ncmListener);
ncm.addEventListener(&quot;ncBandWidth&quot;,ncmListener);
ncm.addEventListener(&quot;ncStreamLength&quot;,ncmListener);

//call the connect method on NCM instance
ncm.connect(k_SERVERNAME,k_APPNAME);
</pre>
<p><a href="http://www.derekentringer.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5kZXJla2VudHJpbmdlci5jb20vZmxhc2hfYmFuZHdpZHRoX2FuZF9wb3J0X2RldGVjdGlvbi8=" target=\"_blank\">Click here to see your bandwidth results.</a></p>
<p><a href="http://www.derekentringer.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5kZXJla2VudHJpbmdlci5jb20vZG93bmxvYWRzL2ZsYXNoX2JhbmR3aWR0aF9hbmRfcG9ydF9kZXRlY3Rpb24uemlw">Download the source</a></p>
<p>This tutorial has been updated, and is available in the following 3-part series:</p>
<p><a href="http://www.derekentringer.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5kZXJla2VudHJpbmdlci5jb20vYmxvZy9mbGFzaC1tZWRpYS1zZXJ2ZXItc3RyZWFtaW5nLXNwZWVkLXRlc3RpbmctcGFydC0xLWRldGVjdC11cGxvYWQtZG93bmxvYWQtYW5kLWxhdGVuY3ktc3BlZWRzLw==">Flash Media Server Streaming Speed Testing [Part 1] &#8211; Detect Upload, Download, and Latency Speeds</a></p>
<p><a href="http://www.derekentringer.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5kZXJla2VudHJpbmdlci5jb20vYmxvZy9mbGFzaC1tZWRpYS1zZXJ2ZXItc3RyZWFtaW5nLXNwZWVkLXRlc3RpbmctcGFydC0yLWRldGVjdC11cGxvYWQtZG93bmxvYWQtYW5kLWxhdGVuY3ktc3BlZWRzLWFuZC1wb3J0LWNvbm5lY3Rpb24v">Flash Media Server Streaming Speed Testing [Part 2] &#8211; Detect Upload, Download, and Latency Speeds, and Port Connection</a></p>
<p><a href="http://www.derekentringer.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5kZXJla2VudHJpbmdlci5jb20vYmxvZy9mbGFzaC1tZWRpYS1zZXJ2ZXItc3RyZWFtaW5nLXNwZWVkLXRlc3RpbmctcGFydC0zLWNvbXBhcmUtbXVsdGlwbGUtc2VydmVyLXJlc291cmNlcy1wb3J0LWNvbm5lY3Rpb25zLWRldGVjdC11cGxvYWQtZG93bmxvYWQtYW5kLWxhdGVuY3ktc3BlZWQv">Flash Media Server Streaming Speed Testing [Part 3] &#8211; Compare Multiple Server Resources, Port Connections, Detect Upload, Download, and Latency Speed</a></p>
 <img src="http://www.derekentringer.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=118" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://www.derekentringer.com/blog/flash-bandwidth-port-detection/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Use Actionscript to Detect Flash Version</title>
		<link>http://www.derekentringer.com/blog/actionscript-detect-flash-version/</link>
		<comments>http://www.derekentringer.com/blog/actionscript-detect-flash-version/#comments</comments>
		<pubDate>Fri, 24 Oct 2008 17:37:18 +0000</pubDate>
		<dc:creator>Derek J Entringer</dc:creator>
				<category><![CDATA[Flash]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[actionscript]]></category>
		<category><![CDATA[is]]></category>
		<category><![CDATA[my]]></category>
		<category><![CDATA[version]]></category>
		<category><![CDATA[what]]></category>

		<guid isPermaLink="false">http://derekentringer.com/blog/?p=111</guid>
		<description><![CDATA[
			
				
			
		

A friend my mine just asked me how he could find out how to detect his version of flash, so I wrote a quick bit of AS2 to help him out. Here&#8217;s a quick and easy way to detect a users flash version from within your Flash project.

//trace(eval(&#34;$version&#34;));
version = eval(&#34;$version&#34;);
//The operating system: WIN, MAC, LNX
var osType;
//The player versions. 9,0,115,0
var majorVersion; 9
var majorRevision; 0
var minorVersion; 115
var minorRevision; 0
vers.text = version;
osArray = version.split(' ');
osType = osArray[0];
versionArray = osArray[1].split(',');
majorVersion = versionArray[0];
majorRevision = versionArray[1];
minorVersion = versionArray[2];
minorRevision = versionArray[3];
feedback.text = &#34;Operating System: &#34;+osType + &#34;\n&#34; ...]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="clear:left; float:left; margin-top:10px; margin-bottom: 10px; margin-right:12px; margin-left:2px;">
			<a href="http://www.derekentringer.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2FwaS50d2VldG1lbWUuY29tL3NoYXJlP3VybD1odHRwJTNBJTJGJTJGd3d3LmRlcmVrZW50cmluZ2VyLmNvbSUyRmJsb2clMkZhY3Rpb25zY3JpcHQtZGV0ZWN0LWZsYXNoLXZlcnNpb24lMkY="><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.derekentringer.com%2Fblog%2Factionscript-detect-flash-version%2F&amp;source=derekentringer&amp;style=normal&amp;service=TinyURL.com" height="61" width="50" /><br />
			</a>
		</div>
<p><!--PLAIN_TEXT--><br />
A friend my mine just asked me how he could find out how to detect his version of flash, so I wrote a quick bit of AS2 to help him out. Here&#8217;s a quick and easy way to detect a users flash version from within your Flash project.</p>
<pre class="brush: as3;">
//trace(eval(&quot;$version&quot;));
version = eval(&quot;$version&quot;);
//The operating system: WIN, MAC, LNX
var osType;
//The player versions. 9,0,115,0
var majorVersion; 9
var majorRevision; 0
var minorVersion; 115
var minorRevision; 0
vers.text = version;
osArray = version.split(' ');
osType = osArray[0];
versionArray = osArray[1].split(',');
majorVersion = versionArray[0];
majorRevision = versionArray[1];
minorVersion = versionArray[2];
minorRevision = versionArray[3];
feedback.text = &quot;Operating System: &quot;+osType + &quot;\n&quot; +
	&quot;Major Version: &quot;+majorVersion + &quot;\n&quot; +
	&quot;Major Revision: &quot;+majorRevision + &quot;\n&quot; +
	&quot;Minor Version: &quot;+minorVersion + &quot;\n&quot; +
	&quot;Minor Revision: &quot;+minorRevision;
trace(&quot;Operating System: &quot;+osType);
trace(&quot;Major Version: &quot;+majorVersion);
trace(&quot;Major Revision: &quot;+majorRevision);
trace(&quot;Minor Version: &quot;+minorVersion);
trace(&quot;Minor Revision: &quot;+minorRevision);
</pre>
<p><a href="http://www.derekentringer.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5kZXJla2VudHJpbmdlci5jb20vZmxhc2hfdmVyc2lvbl9kZXRlY3Rpb24v" target=\"_blank\">Click here to see your version of flash.</a></p>
<p><a href="http://www.derekentringer.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5kZXJla2VudHJpbmdlci5jb20vZG93bmxvYWRzL2ZsYXNoX3ZlcnNpb25fZGV0ZWN0aW9uLnppcA==">Download the source</a></p>
 <img src="http://www.derekentringer.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=111" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://www.derekentringer.com/blog/actionscript-detect-flash-version/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
