A Flash Developer Resource Site

Results 1 to 7 of 7

Thread: data limit to sockets? data events stop firing!

  1. #1
    Senior Member
    Join Date
    Apr 2004
    Location
    LA
    Posts
    349

    data limit to sockets? data events stop firing!

    I have a pretty elaborate class that extends Socket and performs some serialization and data protocol stuff. It works pretty well when I send small messages. However, when I send anything over about 132KB at once, the SOCKET_DATA progress events stop firing -- or at least the function I've got listening for them does. My class is called RPCSocket and I assign the socketDataHandler function like this in my constructor:
    addEventListener(ProgressEvent.SOCKET_DATA, socketDataHandler);

    My socketDataHandler function (with lots of comments) is attached. Is there some limit to how much data can be sent over a socket at once? Is there something wrong with my code? Here's the trace output:

    Code:
    socketdatahandler
    bytesAvail:4380
    buffer length:0
    reading bytes into buffer for concat
    buffer length after concat:4380
    buffer state:0
    BUFFER state is ready
    and we got enough bytes: 4380
    setting mesg length to 500040
    buffer state set to 1
    trimming 4 bytes off buffer
    buffer length:4376
    the big check
    end of message peel loop
    socket data handler end
    socketdatahandler
    bytesAvail:8760
    buffer length:4376
    reading bytes into buffer for concat
    buffer length after concat:13136
    buffer state:1
    the big check
    end of message peel loop
    socket data handler end
    socketdatahandler
    bytesAvail:64240
    buffer length:13136
    reading bytes into buffer for concat
    buffer length after concat:77376
    buffer state:1
    the big check
    end of message peel loop
    socket data handler end
    socketdatahandler
    bytesAvail:54020
    buffer length:77376
    reading bytes into buffer for concat
    buffer length after concat:131396
    buffer state:1
    the big check
    end of message peel loop
    socket data handler end
    PHP Code:
           private function socketDataHandler(evt:ProgressEvent):void {
                
    trace('socketdatahandler');
                var 
    tmpBuf:ByteArray;
                var 
    messageBytes:ByteArray;
                
                
    log.write('RPCSocket.socketDataHandler invoked:' +  evtLog.LOW);

                var 
    bytesAvail:int super.bytesAvailable;
                
    trace('bytesAvail:' bytesAvail);
                
    trace('buffer length:' buffer.length);            
                var 
    totalLength:int buffer.length bytesAvail;
                if (
    totalLength RPCSocket.MAX_BUFFER_LENGTH) {
                    
    // read all the socket data and dump it
                    
    tmpBuf = new ByteArray();
                    
    trace('reading all bytes to empty buffer');
                    
    super.readBytes(tmpBuf0bytesAvail);
                    
    tmpBuf null;

                    
    resetBuffer();
                    
    log.write('RPCSocket.socketDataHandler failed.  Buffer length of ' +
    totalLength ' exceeds maximum allowed of ' RPCSocket.MAX_BUFFER_LENGTH +
    ' bytes.  Buffer reset.'Log.HIGH);
                    
    dispatchEvent(new IOErrorEvent(IOErrorEvent.IO_ERRORfalsefalse,
    'RPCSocket.socketDataHandler failed.  Maximum buffer length of ' totalLength ' exceeds
    maximum allowed of ' 
    RPCSocket.MAX_BUFFER_LENGTH ' bytes.  Buffer reset.'));
                    return;
                }
                
                
    // otherwise, add all the socket's available data to the buffer
                
    trace('reading bytes into buffer for concat');
                
    super.readBytes(bufferbuffer.length);
                
    trace('buffer length after concat:' buffer.length);            
                
    // try to peel off any messages that might live on the buffer
                
    do {
                    
    trace('buffer state:' bufferState);
                    switch(
    bufferState) {
                        case 
    RPCSocket.BUFFER_STATE_READY :
                            
    trace('BUFFER state is ready');
                            if (
    buffer.length RPCSocket.MESSAGE_LENGTH_INDICATOR_BYTES) {
                                return; 
    // not enough to do anything yet
                            
    }
                            
    trace("\tand we got enough bytes: " buffer.length);
                            
    // otherwise, we can at least read the incoming message length
                            
    incomingMessageLength buffer.readUnsignedInt();
    trace('setting mesg length to ' incomingMessageLength);
                            
    // sanity check
                            
    if (incomingMessageLength == 0) {
                                
    trace('DAMN have to reset buffer');
                                
    resetBuffer();
                                
    log.write('Incoming message length of zero. Flushing buffer.'Log.HIGH);
                                return;
                            }
                            
    bufferState RPCSocket.BUFFER_STATE_READING;
    trace('buffer state set to ' RPCSocket.BUFFER_STATE_READING);
                            
    // NOTE - at this point, the buffer's position has advanced
                            // let's trim those few bytes off the beginning
                            
    trace('trimming 4 bytes off buffer');                    
                            
    tmpBuf = new ByteArray();
                            
    buffer.readBytes(tmpBuf0);
                            
    buffer = new ByteArray();
                            
    tmpBuf.readBytes(buffer0);
                            
    tmpBuf null;
                            
    trace('buffer length:' buffer.length);
                            break;
                            
                        case 
    RPCSocket.BUFFER_STATE_READING :
                            
    // nothing to do here...might be some day
                            
    break;
                        default:
                            
    resetBuffer();
                            
    log.write('Unexpected buffer state. Flushing buffer.'Log.HIGH);
                            return;
                    } 
    // switch bufferState
                    
                    
    if (bufferState == RPCSocket.BUFFER_STATE_READY) {
                        
    trace('buffer state is ready, returning');
                        return;
                    }
                    
    trace('the big check');                
                    if ((
    bufferState == RPCSocket.BUFFER_STATE_READING) && (buffer.length >= incomingMessageLength)) {
    trace('we in now');
                        
    // we have our message!  peel it off
                        
                        // read the message's bytes into a new array
                        
    messageBytes = new ByteArray();
                        
    trace('reading bytes into MessageBytes');
                        
    buffer.readBytes(messageBytes0incomingMessageLength);
                        
                        
    // truncate the buffer
                        
    trace('truncating buffer after message bytes out');
                        
    tmpBuf = new ByteArray();
                        
    buffer.readBytes(tmpBuf0);
                        
    buffer = new ByteArray();
                        
    tmpBuf.readBytes(buffer0);
                        
    trace('buffer length after trunc:' buffer.length);
                        
                        
    // reset the buffer state
                        
    bufferState RPCSocket.BUFFER_STATE_READY;
                        
    trace('bufferstate set to ' bufferState);
                        
    incomingMessageLength 0;
                        
                        
    // unserialize the message and execute the RPC therein
                        
    var incomingRPC:Array = unserialize(messageBytes);
                        if (!
    incomingRPC || (!(incomingRPC is Array))) {
                            
    log.write('RPCSocket.socketDataHandler failed.  Data received
    did not unserialize properly to an array.'
    Log.HIGH);
                        }
                        var 
    serviceName:String incomingRPC[0];
                        var 
    eventName:String incomingRPC[1];
            
                        if (!
    serviceName) {
                            
    // no service!  dispatchEvent to all registered services
                            
    log.write('RPCSocket.socketDataHandler failed.  RPC received
    from server with no serviceName.'
    Log.HIGH);
                            
    dispatchEvent(new IOErrorEvent(IOErrorEvent.IO_ERROR,
    falsefalse'RPCSocket.socketDataHandler failed.  RPC received with no serviceName.'));
                            return;
                        }
            
                        var 
    svc:FlashMOGService services[serviceName];
                        if (!
    svc) {
                            
    // service doesn't exist!
                            
    log.write('RPCSocket.socketDataHandler failed.  No service
    named ' 
    serviceName '.'Log.HIGH);
                            
    dispatchEvent(new IOErrorEvent(IOErrorEvent.IO_ERROR,
    falsefalse'RPCSocket.socketDataHandler failed.  No service named ' serviceName '.'));
                            return;
                        }
                        if (!
    eventName) {
                            
    // we have a serviceName but no event name!
                            // broadcast error to that one service only
                            
    log.write('RPCSocket.socketDataHandler failed.  RPC received
    with no eventName.'
    Log.HIGH);
                            
    svc.dispatchEvent(new IOErrorEvent(IOErrorEvent.IO_ERROR,
    falsefalse'RPCSocket.socketDataHandler failed.  RPC received with no eventName.'));
                            return;
                        }
            
                        var 
    args:Array = incomingRPC[2];
                        
    svc.dispatchEvent(new FlashMOGDataEvent(FlashMOGDataEvent.DATAfalsefalseargs));
            
                        var 
    methodFunc:Function = services[serviceName].client[eventName];
                        if (
    methodFunc is Function) {
                            
    methodFunc.apply(nullargs);
                        }
                        
                    } 
    // if bufferState is READ and buffer.length >= incomingMessageLength
                    
    trace ('end of message peel loop');
                } while ((
    bufferState == RPCSocket.BUFFER_STATE_READY) &&
    (
    buffer.length RPCSocket.MESSAGE_LENGTH_INDICATOR_BYTES));
                
                
    log.write('RPCSocket.socketDataHandler end reached:' +  evtLog.LOW);
    trace('socket data handler end');
            }
    // function socketDataHandler() 
    Write multiplayer games with FlashMOG 0.3.1
    Try the MyPlan Salary Calculator

  2. #2
    Senior Member
    Join Date
    Apr 2004
    Location
    LA
    Posts
    349
    OK I am still trying to figure this out. The idea is pretty simple. The server has sent some data over a socket. This data consists of a 4-byte message header which describes the length of the incoming message and then the message itself. In this particular case, my message has a length of 500040 bytes.

    My code receives the first installment of this long socket message in a block of 4,380 bytes. It peels off the 4 bytes at the beginning and interprets them to get the incoming message length of 500040. The remaining 4376 bytes go into a byteArray var called buffer. As more blocks of data arrive, the socketDataHandler function is repeatedly triggered and the extra blocks are concatenated into the buffer.

    The problem happens when the buffer ByteArray reaches a length of 131396. For some reason, once this length is reached, the buffer cannot hold any more data and the socketDataHandler events stop.

    Is this a limitation of the ByteArray object's size? Does it have something to do with the Socket data type? Does anyone know?
    Write multiplayer games with FlashMOG 0.3.1
    Try the MyPlan Salary Calculator

  3. #3
    Will moderate for beer
    Join Date
    Apr 2007
    Location
    Austin, TX
    Posts
    6,801
    The docs don't seem to indicate any inherent size limit on ByteArrays. Even if there were, it shouldn't be that low, since BitmapData supports sizes up to 16777215 pixels, which is quite a few more bytes than you've got there.

  4. #4
    Senior Member
    Join Date
    Apr 2004
    Location
    LA
    Posts
    349
    And yet the socketDataHandler function stops getting triggered. Do I have to pull out wireshark and start sifting packets?
    Write multiplayer games with FlashMOG 0.3.1
    Try the MyPlan Salary Calculator

  5. #5
    Will moderate for beer
    Join Date
    Apr 2007
    Location
    Austin, TX
    Posts
    6,801
    Are you sure of that number? 131072 would at least be 2^17, which I could see being a boundary condition of some sort (perhaps on an index). But no, that doesn't seem to help much.

    Break out wireshark, see if the packets are still coming in.

  6. #6
    Senior Member
    Join Date
    Apr 2004
    Location
    LA
    Posts
    349
    What appears to be happening is that the bytes beyond 131396 are never delivered from the Socket object.

    I have a button on my flash movie which triggers the large delivery of bytes from the server. I click it once and flash will trace the message in my original post at which point the socketDataHandler events stop triggering -- it's as though the other bytes disappeared. What's kind of interesting is that the last time socketDataHandler runs, the bytesAvailable amount on the socket is EXACTLY enough to increase the buffer to that magic number of 131396:
    Code:
    bytesAvail:54020
    buffer length:77376
    54020+77376=131396

    Here's another trace...
    Code:
    socketdatahandler
    bytesAvail:1460
    buffer length:0
    reading bytes into buffer for concat
    	 concat:1460
    buffer state:0
    BUFFER state is ready
    	and we got enough bytes: 1460
    setting mesg length to 500040
    buffer state set to 1
    trimming 4 bytes off buffer
    buffer length:1456
    the big check
    end of message peel loop
    socket data handler end
    socketdatahandler
    bytesAvail:8760
    buffer length:1456
    reading bytes into buffer for concat
    	 concat:10216
    buffer state:1
    the big check
    end of message peel loop
    socket data handler end
    socketdatahandler
    bytesAvail:64240
    buffer length:10216
    reading bytes into buffer for concat
    	 concat:74456
    buffer state:1
    the big check
    end of message peel loop
    socket data handler end
    socketdatahandler
    bytesAvail:56940
    buffer length:74456
    reading bytes into buffer for concat
    	 concat:131396
    buffer state:1
    the big check
    end of message peel loop
    socket data handler end
    Please note:
    Code:
    bytesAvail:56940
    buffer length:74456
    56940+74456=131396

    I feel like I'm in a bad nicolas cage movie.

    At any rate, I'm busting out WireShark now to see if any information is getting lost in transit.
    Write multiplayer games with FlashMOG 0.3.1
    Try the MyPlan Salary Calculator

  7. #7
    Senior Member
    Join Date
    Apr 2004
    Location
    LA
    Posts
    349
    Oops...forgot to mention that if I click the button AGAIN after triggering the stalled results above, the buffer can grow quite large without any problem. It would appear not to be a ByteArray limitation but rather a delivery failure.
    Write multiplayer games with FlashMOG 0.3.1
    Try the MyPlan Salary Calculator

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  




Click Here to Expand Forum to Full Width

HTML5 Development Center