1

If you write a simple object to a socket:

var o:Object = new Object();
o.type = e.type;
o.params = e.params;
_socket.writeObject(o);
_socket.flush();

Then on the client do you simply use:

private function onData(e:ProgressEvent):void
{
    var o:Object = _clientSocket.readObject();
}

Or do you have to implement some way of checking all of the data has been received recieved before calling .readObject()

davivid
  • 5,910
  • 11
  • 42
  • 71

4 Answers4

2

There's 2 approaches:

If you're confident that your object will fit into one packet, you can do something like:

var fromServer:ByteArray = new ByteArray;

while( socket.bytesAvailable )
    socket.readBytes( fromServer );

fromServer.position = 0;
var myObj:* = fromServer.readObject();

If you have the possibility of having multiple packet messages, then a common usage is to prepend the message with the length of the message. Something like (pseudo code):

var fromServer:ByteArray    = new ByteArray();
var msgLen:int              = 0;

while ( socket.bytesAvailable > 0 )
{
    // if we don't have a message length, read it from the stream
    if ( msgLen == 0 )
        msgLen = socket.readInt();

    // if our message is too big for one push
    var toRead:int  = ( msgLen > socket.bytesAvailable ) ? socket.bytesAvailable : msgLen;
    msgLen          -= toRead; // msgLen will now be 0 if it's a full message

    // read the number of bytes that we want.
    // fromServer.length will be 0 if it's a new message, or if we're adding more
    // to a previous message, it'll be appended to the end
    socket.readBytes( fromServer, fromServer.length, toRead );

    // if we still have some message to come, just break
    if ( msgLen != 0 )
        break;

    // it's a full message, create your object, then clear fromServer
}

Having your socket able to read like this will mean that multiple packet messages will be read properly as well as the fact that you won't miss any messages where 2 small messages are sent almost simultaneously (as the first message will treat it all as one message, thereby missing the second one)

divillysausages
  • 7,883
  • 3
  • 25
  • 39
  • not really as i've never tested it :) - i had to implement this as we could sometimes get messages quickly (i.e. 2 small messages) and i didn't want to miss them. it's rare (for me anyway) that a message goes over multiple calls, but it does happen. Socket is based on TCP, so this might give you an idea: http://stackoverflow.com/questions/2613734/maximum-packet-size-for-a-tcp-connection – divillysausages Sep 09 '11 at 09:25
  • another thing you can do is compress the message (using zlib) before you send it, then use `ByteArray.uncompress()` before calling `readObject()` – divillysausages Sep 09 '11 at 09:28
  • The loop check does not work. I have gotten multiple onData calls when receiving an image even with the loop calls. – Boon Feb 03 '14 at 23:30
  • What it lets you do is read a number of bytes at a time (i.e. if you have multiple messages in one data packet) - if you read everything all at once, then you don't need the `while`. If you're getting multiple `onData` calls for you image, perhaps it's coming in over multiple packets? – divillysausages Feb 04 '14 at 09:37
1

Rule # 1 when dealing with TCP: it is an octet stream transfer protocol. You may never ever assume anything about how many octets (8 bit long values, commonly called bytes) you get in one go, always write code that can deal with any amount, both too few and too many. There is no gurantee that the write will not be split into multiple reads. There is also no gurantee that a single read will be from a single write.

Henke37
  • 11
  • 1
0

The way I handled it was to make a call back that the server tell the client that the null bit was received.
The null bit is appended to the end of the data string you are sending to the server.

String.fromCharCode(0)

Also in your case you are doing

_socket.writeObject(o);

You should be sending a string not an object.
So Like this.

_socket.writeUTFBytes( 'Hellow World" + String.fromCharCode(0) );

NOTE *************
And one thing that most first time socket creators over look is the fact that the first request to from the client to the server over the port that the socket is connected on is a request for the crossdomainpolicy.xml

The_asMan
  • 6,364
  • 4
  • 23
  • 34
0

If you only wish to send Objects, the simplest solution is if you send an int(size) before every object. Its not important to send the exact size, you can send a bit less. In my case, I've sent a bitmapdata, and the width and height of the object. obviously the bitmapdata's size is so big, its okay if you send only that, and ignore the rest.

var toRead=0;
protected function onSocketData(event:ProgressEvent):void{
                if(toRead==0) {
                toRead=socket.readInt() 
            }
            if(socket.bytesAvailable>toRead){
                var recieved:Object=socket.readObject() 
                /*do stuff with recieved object*/
                toRead=0
            }
csomakk
  • 5,369
  • 1
  • 29
  • 34