views:

497

answers:

2

I'm writing a Comet-like app using Flex on the client and my own hand-written server.

I need to be able to send short bursts of data from the client at quite a high frequency (e.g. of the order of 10ms between sends).

I also need the server to push short bursts of data at a similarly high frequency.

I'm using NetConnection.call() to send the data to the server, and URLStream (with chunked encoding) to push the data from the server to the client.

What I've found is that the data isn't being sent/received as soon as it's available. For example, in IE, it seems the data is sent every 200ms rather than as soon as NetConnection.call() is called. Similarly, URLStream isn't making the data available as soon as the server is sending it.

Judging by the difference in behaviour between the browsers, it seems as though the Flash Player (version 10) is relying on the host browser to do all the comms. Can anyone confirm this? Update: This is very likely as only the host browser would know about the proxy settings that might be set.

I've tried using the Socket class and there's no problem with speed there: it works perfectly. However, I'd like to be able to use HTTP-based (port 80) connections so that my app can run in heavily fire-walled environments (I tried using a Socket over port 80, but that has its problems).

Incidentally, all development/testing has been done on an internal LAN, so bandwidth/latency is not an issue.

Update: The data being sent/received is in small packets and doesn't need to be in any particular format. For example, I might need to send a short array of Numbers, and this could either be encoded in AMF (e.g. via NetConnection.call()) or could be put into GET parameters (e.g. using sendToURL()). The main point of my question is really to see whether anyone else has experienced the same problem in calling NetConnection/URLStream frequently, and whether there is a workaround (it's also possible that the fault lies with my server code of course, rather than Flash).

Thanks.

A: 

I'm almost 100% sure the player relies on the browser for such communications. Can't find an official page stating so atm, but check this out for example:

Applications hosting the Flash Player ActiveX control or Flash Player plug-in can use the EnforceLocalSecurity and DisableLocalSecurity API calls to control security settings.

Which I think somehow implies the idea. Also, I've suffered some network related bugs on FF/IE only which again points out to the player using each browser for networking (otherwise there wouldn't be such differences).

And regarding your latency problem, I think that if speed is critical, your best bet is sockets. You have some work to do, but seems possible, check out the docs again:

This error occurs in SWF content.
Dispatched if a call to Socket.connect() attempts to connect either to a server outside the caller's security sandbox or to a port lower than 1024. You can work around either problem by using a cross-domain policy file on the server.

HTH,

Juan

Zárate
Thanks for your answer Juan. Implementing sockets is not a problem (I've already got working code with a cross-domain file). The problem is getting past people's firewalls.
Well, that's why I added the last link, you should be able to bypass the firewalls going through port 80 and for that you need to implement the crossdomain. Or am I missing something else?
Zárate
I think it depends on the proxy. I get the impression that some proxies are very strict and check that each packet they get is valid HTTP. This in itself isn't a problem because I could write an HTTP client over flash.net.Socket. However, when you call Socket.connect(), it sends the string "<policy-file-request/>" (requesting the x-domain file), and because that isn't a valid HTTP header, I'm assuming some proxies will block it. There is a way to tunnel through a proxy, but it has its own problems: http://weblogs.macromedia.com/cantrell/archives/2006/07/a_proxy-savvy_s.html
+1  A: 

Turns out the problem had nothing to do with Flash/Flex or any of the host browsers. The problem was in my server code (written in C++ on Linux), and without access to my source code the cause is hard to find (so I couldn't have hoped for an answer from this forum).

Still - thank you everyone who chipped in.

It was only after looking carefully at the output shown in Wireshark that I noticed the problem, which was twofold:

Nagle's algorithm

I was sending replies in multiple packets by calling write() multiple times (e.g. once for the HTTP response header, and again for the HTTP response body). The server's TCP/IP stack was waiting for an ACK for the first packet before sending the second, but because of Nagle's algorithm the client was waiting 200ms before sending back the ACK to the first packet, so the server took at least 200ms to send the full HTTP response.

The solution is to use send() with the flag MSG_MORE until all the logically connected blocks are written. I could also have used writev() or setsockopt() with TCP_CORK, but it suited my existing code better to use send().

Chunk-encoded streams

I'm using a never-ending HTTP response with chunk encoding to push data back to the client. Naggle's algorithm needs to be turned off here because even if each chunk is written as one packet (using MSG_MORE), the client OS TCP/IP stack will still wait up to 200ms before sending back an ACK, and the server can't push a subsequent chunk until it gets that ACK.

The solution here is to ask the server not to wait for an ACK for each sent packet before sending the next packet, and this is done by calling setsockopt() with the TCP_NODELAY flag.

The above solutions only work on Linux and aren't POSIX-compliant (I think), but that isn't a problem for me.