Update
The Flash documentation team has confirmed the documentation is incorrect. Data is sent as soon as you write to the Socket.


Flash's Socket class documentation says the following:

flush() method
Flushes any accumulated data in the socket's output buffer. Data written by the write methods is not immediately transmitted; it is queued until the flush() method is called.

Unfortunately, this is not the case. The moment you write to a connected socket, it sends the data and the server receives it. You do not need to call flush(), and, in fact, calling flush() has no effect as far as the server or Flash is concerned.

The socket automatically sends as little as 1 byte. socket.writeByte(0) is immediately sent across the socket. Data is not queued, it is immediately transmitted, so calling flush() doesn't do anything because the data is already sent. There is no difference from the server's perspective whether I call flush() or not, and I can write millions of bytes on a Socket and never call flush() and there is no negative effect as far as all testing I have conducted has been able to show.

Based on my tests, Flash sends data across the Socket in 536 byte packets. Anything larger than 536 bytes gets split into separate packets. So, if you send 537 bytes, Flash sends two packets, one that's 536 bytes and one that's 1 byte.

The internal limit that Flash can send via Socket appears to be 524,744 bytes. If you set up your server to not read off the socket, 524,744 bytes is the point that Flash's socket becomes blocked. However, Flash does not let you know that the Socket is blocked or that there are any bytes sitting on the Socket unsent.

This behavior is exacerbated by the fact that there is no way to track progress on Socket sending, only receiving. There is no event that fires if you're blocked, and you have no way of knowing that the server did not receive your entire transmission unless you have some kind of expected response that you did not receive within a certain time limit, which is not something you can reliably measure considering latency and/or varying bandwidths, and the fact that you have no idea how much data the server has received.

If you send 1,000,000 bytes and set up your server to wait until you send 524,744 bytes to read it, Flash does not even need you to call flush() to send the remaining 475,256 bytes, it happens automatically. No flush() required, and you don't even know that the Socket was blocked.

It's worth pointing out that if the server has a receive buffer (we set it to 8040 bytes), Flash does not honor it when running in the IDE, running as a SWF in the debug player on the desktop, or in AIR. It only honors it when it's running in a browser (tested in Chrome, Firefox and IE on Windows). Regardless, Flash does not report that only 8040 bytes were sent, and, again, flush() was not called but the bytes were sent anyway.

The behavior is identical whether you use socket.writeByte() and write 1 byte to the socket at a time, or use writeBytes() and write all the bytes to the socket at once.

FileReference lets you track progress on a HTTP Socket POST of bytes. I hope they soon will give us progress on the Socket sending, and, perhaps, allow the Socket to wait for you to tell it to upload (via flush()).

Tagged with:
 

16 Responses to Flash Socket Class Does Not Wait For Flush

  1. Gardner says:

    Unfortunately sockets are kinda like this at the system level as well. Flushing just ensures that there is no queued data but once you chuck the data into send() it gets sent whenever the tcp stack gets around to it. Check out http://msdn.microsoft.com/en-us/library/ms740149%28VS.85%29.aspx Specifically: "If no error occurs, send returns the total number of bytes sent, which can be less than the number requested to be sent in the len parameter." At least the winsock api tell you how many bytes you've sent…

  2. Steven Sacks says:

    Ok, so it's confirmed (from you and elsewhere) that Socket sends the data the moment you write anything to it.

    The documentation is wrong throughout (every write function says it doesn't send until you call flush, and flush says it sends the data, but, in fact, does nothing because the data is already sent instantly).

  3. Jody Bleyle says:

    Nice catch, Steven, thank you. I'm updating the documentation source now and we'll push the changes live as soon as we can.

    Jody Bleyle
    Sr. Technical Writer
    Adobe Systems, Inc.

  4. Steven Sacks says:

    Thanks! Now how about returning progress, or being able to see how many bytes remain on the socket so I can tell if the socket is blocked, etc.

  5. maliboo says:

    As Steven said there are huge problems with getting sending progress with Socket class. So don;t forget to vote on this bug@Adobe JIRA:
    http://bugs.adobe.com/jira/browse/FP-6
    ;)

  6. Steven Sacks says:

    It's been almost 3 months and the documentation remains unchanged. Will you be updating this anytime soon?

  7. 62316e says:

    So, how to flush socket?

  8. Steven Sacks says:

    There is no flushing of a socket. The moment you say socket.writeWhatever, the bytes are sent to the server immediately.

  9. Joe Ward says:

    As to the flush() behavior, on Mac and Linux, flush() is called implicitly between execution frames. So if you wrote two bytes in different write calls in the same function, for example, those two bytes are sent together. If the writes were separated by an async event, then they would be sent separately.

    However, on Windows, data is never sent unless you call flush(). The platform inconsistency is a bug, but the docs were essentially correct (just incomplete).

  10. Steven Sacks says:

    That is incorrect. You haven't tested this. If you had, you would know that what you just said is wrong.

    I am on Windows and when I write to the Socket, the server immediately receives it. Same thing happens on Mac and Linux. There is no platform inconsistency.

    I'm surprised that Adobe still hasn't updated the documentation.

  11. psh says:

    Flash rides on TCP sockets. TCP does not guarantee delivery or any timing of it. All you can say about it is that any data that is received, will be received free of errors and in the order it was sent. Anything else is circumstantial behavior.

    Flash might try to reduce the overhead of pushing individual tiny buffers down to the socket layer, instantaneously. The best a flush call can do is to request that any pending data be pushed into the kernel socket buffers. But it does not guarantee that it will. It cannot, short of making the flush function a potentially indefinitely blocking call.

    The real weakness in the Flash socket api is lack of progress event for when the socket buffer opens up for more input. Seems like the best you can do now is to keep re-trying a send with a timer callback until it goes through.

  12. Joha says:

    Hello!
    Does anyone have any news about this article? I have realy problem with flush() method of the socket. Maybe there is workarount for this issue?

  13. mika says:

    RTFM :)

    http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/net/Socket.html#flush%28%29

    "On some operating systems, flush() is called automatically between execution frames, but on other operating systems, such as Windows, the data is never sent unless you call flush() explicitly. To ensure your application behaves reliably across all operating systems, it is a good practice to call the flush() method after writing each message (or related group of data) to the socket."

  14. Steven Sacks says:

    I develop on Windows. I did read the fucking manual. The fucking manual is wrong. Maybe instead of reading the fucking manual, you should write some fucking code and verify for yourself that the fucking manual is fucking wrong.

  15. Ryan Williams says:

    I have a flash program running on windows which does not transmit data to the server until I call flush().

    The manual does appear to be correct.
    In my case I only have a single frame fla so i call stop() and do everything in actionscript.

    package {
    public class MyApp extends MovieClip
    {
    public function MyApp()
    {
    stop();

    var socket:Socket = new Socket();
    socket.addEventListener(Event.CONNECT, onSocketConnect);
    socket.connect('localhost',22222);

    function onSocketConnect() {
    for (var i:int=0;i<(1024*1024);i++) {
    socket.writeInt(i);

    // try flushing here
    socket.flush();
    }
    // try flushing here or don't flush at all
    socket.flush();
    socket.close();
    }
    }
    }
    }

  16. Hi there! Do you use Twitter? I'd like to follow you if
    that woud be okay. I'm definitely enjoying your blog and look forward to new updates.

    Feel ffree to visit my web page restaurants near me now google

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Set your Twitter account name in your settings to use the TwitterBar Section.