Archives For socket

Currently when using the flash.net.Socket api, there is no way to
determine that buffered data has been written to the socket. (The flush method is non-blocking and applies only to the actionscript socket buffer).

This is a follow-up to a previous post.

This issue does not arise when using the new File api (and writing to
files), since an event has been included in
flash.filesystem.FileStream: OutputProgressEvent.OUTPUT_PROGRESS

If this (or a similar) event could be added to the Socket api, it
would allow us to:

  • Send large amounts of data on a socket (without causing large memory
    usage as data buffers in memory).
  • Measure the current progress of data being sent on the socket.

We came upon this limitation from using our AS3 http client library, and trying to send large
files as part of a multipart upload. However this issue would arise
when sending any significant amounts of data on a socket. For example, an FTP or bittorrent client would be impossible.

This issue has been discussed in other places, but is probably more
pressing now with the AIR releases.

Update:

Flush

December 27, 2007 — 3 Comments

So I decided to try to overcome the Leopard File.upload() bug by rolling my own http client: as3httpclientlib which even supports https with the TLS (Socket) support from as3crypto (which is great). The HTTP protocol is pretty simple and I figured it would be a good way to learn the internals and look smart reading ancient RFC‘s. All you need is a Socket class and nice, flash api has one at flash.net.Socket

I got everything major working like GET, PUT and POST with multipart/form-data and reading chunked encoding and all that stuff. Not too hard since there are open source http libraries for every major language. I looked at ruby Net::HTTP (stole some regex’s) and Apache Httpclient (stole your multipart boundary).

I got to the point where I was testing uploading larger files, like in:

var client:HttpClient = new HttpClient();
var uri:URI = new URI("http://mybucket.s3.amazonaws.com/big.mp3");
var testFile:File = new File("app:/test/assets/big.mp3");
client.upload(uri, testFile);

It turns out that when you call _socket.flush() (in HttpSocket) it doesn’t actually block, which you might expect. After thinking on it, this isn’t totally shocking since the whole threading model behind actionscript, you don’t really ever block (like there is no such thing as a modal dialog in flash). The problem is without blocking or an event to notify of a flush, the socket just gets filled with the request body all at once (all 800MB’s or whatever file size).

It turns out other people ran into this as well. If you look at (FlexFTP) source, the UploadInv.as file, you will see block of code commented out and replaced by a setInterval(.. , 300). Nice. I guess that upload is capped at ~12kb/sec.

Any of the links in the comments off this blog post are useful too.

If you look at FileStream object you will see it has an outputProgressEvent so that would be useful, you know, if Socket had that too.

I don’t know how you get around this issue, other than trying to guess how fast the socket can transmit and try to stay under that. So now I’m not sure what to do, other than abandon it and come back to it when its fixed, which hopefully will be soon. Thankfully, I can go back to ruby and maybe play with some RubyCocoa or Shoes framework.

Update: Feel free to chime in at Adobe Air Forum or Feature Request/Bug Report Form