3

I'm working on the project in AIR (AS3). I have a Socket Server running on my computer, and two ipads connected over wifi, which should communicate with the server. I wrote a basic "send" function which works this way :

function send(_type:String, _data:String):void
{
    socket.writeObject({ type: _type, data: _data});
    socket.flush();
}

When the server reads a response, it just sends it to the other socket (ipad) to achieve indirect ipad-to-ipad communication. The port is above 1024.

Sometimes, especially when both ipads send a message at approximately the same time, nothing is sent back from the server. I colleague working on a different project but with AIR AS3 sockets use WriteUTFBytes/readUTFBytes instead of my writeObject/readObject and he doesn't seem to have this problem.

My question is basically, is there a fundamental difference between these two functions ? How can I prevent this bug ? I'm suspecting that somehow the server doesn't like to send a message on a socket currently carrying another message. Am I right ?

Update: Server side message handling :

I have a listener for the ProgressEvent.SOCKET_DATA event, which looks like this :

private function onData(e: ProgressEvent):void
{
    var currentSocket:Socket = e.currentTarget as Socket;
    var p:Object = currentSocket.readObject();
    switch(p.type)
    {
    // Process data based on the type of event
    }
}

Update 2 : I've done some debugging with Wireshark, and I've noticed that sometimes, my flash trace says it sent the message, and it doesn't appear in Wireshark (which shows PDU fragment, so I guess even merged packages should show up).

Second thing (third update), is when both ipads send a message at the same time, they are properly shown in Wireshark but the server only reads the first one ! Although both ACK are presents. I don't understand.

4

1 回答 1

0

我不知道它是否能解决你的问题,但是当你做网络工作时,你必须总是准备一个协议,因为你不能保证你会一次收到所有数据。

在您的情况下,您应该在自己发送数据之前发送数据的长度,并且在反序列化之前在服务器端等待足够的数据。

您应该考虑做这样的事情并为每个 DataEvent 调用 read 函数:

package
{
    import flash.display.Sprite;
    import flash.net.Socket;
    import flash.utils.ByteArray;

    public class TestSocket extends Sprite
    {
        public var sendSocket : Socket;
        public var writeBuffer : ByteArray = new ByteArray;
        public var readBuffer : ByteArray = new ByteArray;
        private var readLenght : int = -1;

        public function send(_type:String, _data:String):void
        {
            // Write your object to a buffer to be able to read its lenght
            writeBuffer.clear();
            writeBuffer.writeObject({ type: _type, data: _data});

            // Send the length to the server
            sendSocket.writeInt(writeBuffer.length);

            // Send your object
            writeBuffer.position = 0;
            sendSocket.writeBytes(writeBuffer);

            sendSocket.flush();
        }

        public function read(socket : Socket) : Object
        {
            // Read all avaibles Bytes
            socket.readBytes(readBuffer);

            // Check if we have enough data to read lenght
            if(readLenght == -1 && readBuffer.length > 8)
                readLenght = readBuffer.readInt();

            // Check if we can read object
            if(readLenght != -1 && readBuffer.length >= readLenght + 8)
            {
                // Reset data length
                readLenght = -1;

                // Read object
                var o : Object = readBuffer.readObject();

                // Remove read data
                var tmp : ByteArray = new ByteArray;
                tmp.writeBytes(readBuffer);
                readBuffer.clear();
                readBuffer.readBytes(tmp);

                return o;
            }

            return null;
        }
    }
}
于 2013-05-07T07:54:56.437 回答