Scriptico

FMS and Ghost Connections

In the following article I would like to talk about ghost connections on the FMS server. First of all, what does the term “ghost connection” mean? It is a registered and alive connection on the server without the real client. How could it happen? There are a few scenarios. For instance, the client closed the browser and the client application did not send the termination handshake to the server. One more example is a situation when the client network connection has been changed. Although the client may have some logic to reconnect, the client will establish a new connection to the server. Server, in its turn, will create a new connection and at the same time will keep the previous one alive. Is it a problem? Yes, this is a huge problem and it is a developer responsibility to eliminate the issue from the begging. I wonder why FMS doesn’t have an instrument to avoid ghost connection by default as WebORB does for instance, but there is not much you can do, but to handle it on your own.

The solution is simple and pretty much straightforward. As you probably know, FMS is able to invoke client-side methods and handle the client responses. Thus, the server has to have a loop to call some client method and if there is no response, close the client connection. To make it more sophisticated, the server has to have some time limit to wait for a response in order to avoid endless calls. Thereby, the final approach is to start a timer on the server-side and call the client method every few seconds. If there is a response within some time amount, let’s say 3 seconds, the client is alive; otherwise, the server considers the connection as ghost and closes it.

Now let’s considering the implementation

The client side has to have a void method:

public function ping():void {
	trace("a ping call from the server has been received");
}

The server side has a little bit more code. First of all, let’s create a responder to handle client call responses (all following code snippets are taken from the main.asc server-side application handler)

clientPingResponder = function(client) {
	
	this.onResult = function(res) {  
		trace("ClientPingResponder.onResult Received: " + res);
		clearInterval(client.cleanupTaskId);
	} 
	
    this.onStatus = function(info) {
		trace("ClientPingResponder.onStatus Received: " + info);
	} 
};

Great! We are close to the finish line. Let’s define the following function:

monitorConnection = function(client) {
	
	client.isAlive = function() {
		trace("client.isAlive has been fired");
		client.cleanupTaskId = setInterval(client.dead, 2 * 1000);
		client.call("ping", new clientPingResponder(client));
	}
	
	client.dead = function() {
		trace("cleanupTaskId: " + client.cleanupTaskId);
		trace("monitorTaskId: " + client.monitorTaskId);
		
		clearInterval(client.cleanupTaskId);
		clearInterval(client.monitorTaskId);
		
		trace("ghost connection has been detected");
		
		application.disconnect(client);
	}
	
	client.monitorTaskId = setInterval(client.isAlive, 5*1000);
}

Now, we should run the function above when a client is connecting to the server. Please consider the following:

application.onConnect = function(client) {
        //your code
	monitorConnection(client);
}

The onConnect function is invoked every time when a new client is connecting to the server. More information is available here.

That is it. Most likely the approach above is not an ideal one, so if you have any thoughts to share you are more than welcome to do so!

Category: Action Script, Development

Tagged:

2 Responses

  1. Arjun says:

    I have tried to execute your example, but its showing a Reference Error
    ” ReferenceError: Error #1069: Property ping not found on flash.net.NetConnection and there is no default value. ”

    Can you just help me out from this.
    Thank You

  2. Cyril says:

    Hello Arjun,

    to fix your problem shouldn’t be a big deal. In your client side code, where you are creating an instance of the NetConnection class, define something like the following:

    var connection:NetConnection = new NetConnection();
    connection.client = this;

    Please make sure that the ping method is defined at the same scope as the NetConnection instance.

Leave a Reply

*