|
-
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:' + evt, Log.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(tmpBuf, 0, bytesAvail); 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_ERROR, false, false, '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(buffer, buffer.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(tmpBuf, 0); buffer = new ByteArray(); tmpBuf.readBytes(buffer, 0); 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(messageBytes, 0, incomingMessageLength); // truncate the buffer trace('truncating buffer after message bytes out'); tmpBuf = new ByteArray(); buffer.readBytes(tmpBuf, 0); buffer = new ByteArray(); tmpBuf.readBytes(buffer, 0); 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, false, false, '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, false, false, '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, false, false, 'RPCSocket.socketDataHandler failed. RPC received with no eventName.')); return; } var args:Array = incomingRPC[2]; svc.dispatchEvent(new FlashMOGDataEvent(FlashMOGDataEvent.DATA, false, false, args)); var methodFunc:Function = services[serviceName].client[eventName]; if (methodFunc is Function) { methodFunc.apply(null, args); } } // 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:' + evt, Log.LOW); trace('socket data handler end'); }// function socketDataHandler()
-
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?
-
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.
-
And yet the socketDataHandler function stops getting triggered. Do I have to pull out wireshark and start sifting packets?
-
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.
-
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.
-
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.
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
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|