Most of the functionality you may want in a NetConnection class can be wrapped up in a custom class, which makes it convenient to use in multiple projects. Examine the contents of the NCManager.as file in a text editor and use it as the basis for writing your own custom class. (This file, which is part of the sample files of this tutorial, is based on the NCManager class contained inside the FLVPlayer, by Giacomo "Peldi" Guilizzoni). The NCManager class starts by importing the EventDispatcher class and defining some default functions that this class requires. You'll use events to disseminate information about the progress, results, and errors associated with the connection.
import mx.events.EventDispatcher;
class NCManager extends Object {
var addEventListener:Function;
var removeEventListener:Function;
var dispatchEvent:Function;
var dispatchQueue:Function;
You then define a default connection list. This list consists of an array of objects. Each object possesses attributes that define the protocol and port on which you want to attempt a connection. You can adjust this array to suit the characteristics of your Flash Communication Server installation, which may not have all protocol/port combinations enabled. The protocols and ports will be attempted in the order in which they are defined in this array, so place the most common combinations first.
private var k_DEFAULTCONNLIST = [
{protocol:"rtmp", port:1935},
{protocol:"rtmp", port:443},
{protocol:"rtmpt", port:80}
];
The public function connect is called to initiate the connection attempts. It takes the FCS server name, FCS application name, and a connection list as parameters. If the connection list is not passed, then the default connection list is used.
function connect(p_serverName:String,p_appName:String,p_connList:Array) {
The connect function cycles through the connection list and creates a connection attempt for each protocol/port combination. Notice that there are two functions that are called by the server-side code. The first function is onBWCheck, whose job is to increment and then echo back a counter. This counter serves as the payload during the bandwidth test. The second function is onBWDone, which is called after the bandwidth test is complete to dispatch an event communicating the measured bandwidth value to all listeners.
this["nc"+i].onBWDone = function(p_bw) {
this.owner.dispatchEvent({type:"ncBandWidth", kbps:p_bw});
};
this["nc"+i].onBWCheck = function(counter) {
return ++counter;
};
When a valid NetConnection is found, an event is dispatched that contains a reference to that NetConnection instance as well as the port and protocol that were successful in penetrating the firewall. The code then loops through all the open connections and shuts down the connections that were unsuccessful.
if (info.code == "NetConnection.Connect.Success") {
clearInterval(this.owner.m_flashComConnectTimeOut);
this.owner.dispatchEvent({type:"ncConnected",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<this.owner.m_connList.length; i++) {
if (i == this.connIndex) {
continue;
}
if (this.owner["nc"+i].pending) {
clearInterval(this.owner["ncInt"+i]);
this.owner["nc"+i].onStatus = null;
this.owner["nc"+i].close();
this.owner["nc"+i] = null;
delete this.owner["nc"+i];
}
}
}
The nextConnect function walks through the connection list, trying each protocol and port combination. Notice that the interval at which it does this is 1,500 ms. It is important that you do not attempt subsequent connections too quickly. Very fast, multiple connections from clients could place undue load on the FCS server. In fact, Macromedia strongly recommends that you do not attempt four or more connection attempts with the interval set to 0 (that is, execute the connection attempts in parallel).
private function nextConnect(Void):Void {
clearInterval(this["ncInt"+m_connListCounter]);
this["nc"+m_connListCounter].connect(m_connList[m_connListCounter].protocol+"://"+m_serverName+":"+m_connList[m_connListCounter].port+"/"+m_appName);
if (m_connListCounter<(m_connList.length-1)) {
m_connListCounter++;
this["ncInt"+m_connListCounter] = setInterval(this, "nextConnect", 1500);
}
}
If no connections are successful within the default timeout period (initially set to 60 seconds), then the timeout interval will trigger the onFlashComConnectTimeOut function. This function issues an event and cleans up the open NetConnection instances.
private function onFlashComConnectTimeOut(timeout:Number):Void {
clearInterval(m_flashComConnectTimeOut);
this.dispatchEvent({type:"ncFailedToConnect", timeout:timeout});
for (var i = 0; i<m_connList.length; i++) {
if (this["nc"+i].pending) {
clearInterval(this["ncInt"+i]);
this["nc"+i].onStatus = null;
this["nc"+i].close();
this["nc"+i] = null;
delete this["nc"+i];
}
}
}
A series of public utility functions are defined. getStreamLength accepts a stream name and calls a matching server-side function that reads the duration of the stream. The response triggers an event, with the event object containg the streamlength and the name of the stream.
function getStreamLength(streamName:String) {
var res = new Object();
res.owner = this;
res.name = streamName;
res.onResult = function(p_length) {
this.owner.dispatchEvent({type:"ncStreamLength", length:p_length, name:res.name});
};
m_validNetConnection.call("getStreamLength", res, streamName);
}
getBandWidth calls a server-side function that initiates the bandwidth check. When complete, the onBWDone function of the valid NetConnection instance is called.
function getBandWidth(Void):Void {
m_validNetConnection.call("checkBandwidth", null);
}
getActiveConnection is a utility function which simply returns a reference to the valid NetConnection, or null if it does not exist.
function getActiveConnection(Void):NetConnection {
return m_validNetConnection == undefined ? null : m_validNetConnection;
}