Strange Flash AS3 xml Socket behavior

Posted by Rnd_d on Game Development See other posts from Game Development or by Rnd_d
Published on 2012-03-19T11:06:08Z Indexed on 2012/03/19 18:16 UTC
Read the original article Hit count: 244

Filed under:
|

I have a problem which I can't understand.

To understand it I wrote a socket client on AS3 and a server on python/twisted, you can see the code of both applications below.

Let's launch two clients at the same time, arrange them so that you can see both windows and press connection button in both windows. Then press and hold any button.

What I'm expecting:

Client with pressed button sends a message "some data" to the server, then the server sends this message to all the clients(including the original sender) .

Then each client moves right the button 'connectButton' and prints a message to the log with time in the following format: "min:secs:milliseconds".

What is going wrong:

The motion is smooth in the client that sends the message, but in all other clients the motion is jerky.

This happens because messages to those clients arrive later than to the original sending client. And if we have three clients (let's name them A,B,C) and we send a message from A, the sending time log of B and C will be the same.

Why other clients recieve this messages later than the original sender?

By the way, on ubuntu 10.04/chrome all the motion is smooth. Two clients are launched in separated chromes.

windows screenshot

Can't post linux screenshot, need more than 10 reputation to post more hyperlinks.

Listing of log, four clients simultaneously:

[16:29:33.280858] 62.140.224.1 >> some data
[16:29:33.280912] 87.249.9.98 << some data
[16:29:33.280970] 87.249.9.98 << some data
[16:29:33.281025] 87.249.9.98 << some data
[16:29:33.281079] 62.140.224.1 << some data
[16:29:33.323267] 62.140.224.1 >> some data
[16:29:33.323326] 87.249.9.98 << some data
[16:29:33.323386] 87.249.9.98 << some data
[16:29:33.323440] 87.249.9.98 << some data
[16:29:33.323493] 62.140.224.1 << some data
[16:29:34.123435] 62.140.224.1 >> some data
[16:29:34.123525] 87.249.9.98 << some data
[16:29:34.123593] 87.249.9.98 << some data
[16:29:34.123648] 87.249.9.98 << some data
[16:29:34.123702] 62.140.224.1 << some data

AS3 client code

package 
{
    import adobe.utils.CustomActions;
    import flash.display.Sprite;
    import flash.events.DataEvent;
    import flash.events.Event;
    import flash.events.IOErrorEvent;
    import flash.events.KeyboardEvent;
    import flash.events.MouseEvent;
    import flash.events.SecurityErrorEvent;
    import flash.net.XMLSocket;
    import flash.system.Security;
    import flash.text.TextField;

    public class Main extends Sprite 
    {
        private var socket           :XMLSocket;
        private var textField        :TextField = new TextField;
        private var connectButton    :TextField = new TextField;

    public function Main():void 
    {
        if (stage) init();
        else addEventListener(Event.ADDED_TO_STAGE, init);
    }



    private function init(event:Event = null):void 
    {
            socket = new XMLSocket();
            socket.addEventListener(Event.CONNECT, connectHandler);
            socket.addEventListener(DataEvent.DATA, dataHandler);
            stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);

            addChild(textField);
            textField.y = 50;
            textField.width = 780;
            textField.height = 500;
            textField.border = true;

            connectButton.selectable = false;
            connectButton.border = true;
            connectButton.addEventListener(MouseEvent.MOUSE_DOWN, connectMouseDownHandler);
            connectButton.width = 105;
            connectButton.height = 20;
            connectButton.text = "click here to connect";
            addChild(connectButton);
        }



        private function connectHandler(event:Event):void
        {
            textField.appendText("Connect\n");
            textField.appendText("Press and hold any key\n");
        }



        private function dataHandler(event:DataEvent):void
        {
            var now:Date = new Date();
            textField.appendText(event.data + "          time = " + now.getMinutes() + ":" + now.getSeconds() + ":" + now.getMilliseconds() + "\n");

            connectButton.x += 2;
        }



        private function keyDownHandler(event:KeyboardEvent):void
        {
            socket.send("some data");
        }



        private function connectMouseDownHandler(event:MouseEvent):void
        {
        var connectAddress:String = "ep1c.org";
            var connectPort:Number = 13250;

            Security.loadPolicyFile("xmlsocket://" + connectAddress + ":" + String(connectPort));
            socket.connect(connectAddress, connectPort);
        }
    }
}

Python server code

from twisted.internet import reactor
from twisted.internet.protocol import ServerFactory
from twisted.protocols.basic import LineOnlyReceiver
import datetime

class EchoProtocol(LineOnlyReceiver):
    #####
    name = ""
    id = 0
    delimiter = chr(0)
    #####
    def getName(self):
        return self.transport.getPeer().host

    def connectionMade(self):
        self.id = self.factory.getNextId()
        print "New connection from %s - id:%s" % (self.getName(), self.id)
        self.factory.clientProtocols[self.id] = self

    def connectionLost(self, reason):
        print "Lost connection from "+ self.getName()
        del self.factory.clientProtocols[self.id]
        self.factory.sendMessageToAllClients(self.getName() + " has disconnected.")

    def lineReceived(self, line):
        print "[%s] %s >> %s" % (datetime.datetime.now().time(), self, line)

        if line=="<policy-file-request/>":

            data = """<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM "http://www.adobe.com/xml/dtds/cross-domain-policy.dtd">
<!-- Policy file for xmlsocket://ep1c.org -->
<cross-domain-policy>
    <allow-access-from domain="*" to-ports="%s" />
</cross-domain-policy>""" % PORT
            self.send(data)
        else:
            self.factory.sendMessageToAllClients( line )

    def send(self, line):
        print "[%s] %s << %s" % (datetime.datetime.now().time(), self, line)
        if line:
            self.transport.write( str(line) + chr(0))
        else:
            print "Nothing to send"

    def __str__(self):
       return self.getName()


class ChatProtocolFactory(ServerFactory):
    protocol = EchoProtocol

    def __init__(self):
        self.clientProtocols = {}
        self.nextId = 0

    def getNextId(self):
        id = self.nextId
        self.nextId += 1
        return id

    def sendMessageToAllClients(self, msg):
        for client in self.clientProtocols:
            self.clientProtocols[client].send(msg)

    def sendMessageToClient(self, id, msg):
        self.clientProtocols[id].send(msg)

PORT = 13250
print "Starting Server"
factory = ChatProtocolFactory()
reactor.listenTCP(PORT, factory)
reactor.run()

© Game Development or respective owner

Related posts about networking

Related posts about actionscript-3