2006-06-19
More on Ajax and server push
So far I've looked at two ways of doing server push. The first used a hidden IFRAME which had the SRC attribute set to a persistent connection on the server. The server would push Javascript code along this connection whenever it wanted the client to do something. This had the downside of the browser always displaying a 'loading' indicator as the page never completed loading. From a UI perspective this makes it unusable except as a fallback method of last resort.
The second was outlined in my previous post and used XMLHttpRequest. Like the IFRAME, the request was for a persistent connection. This time the browser wouldn't display a 'loading' indicator and was pretty much exactly what I wanted. I'd prefer it if I didn't have to close the connection after each event to prevent the need to re-establish a connection as this limits scalability a little.
The problem with not closing the connection is you don't know when an event is completely sent back to the client so there is no real guarantee that the client has received the entire event data at one time.
A way of getting around this is to use a mime type of multipart/x-mixed-replace. This allows you to define the 'chunks' in your page. So the browser knows when to process each chunk. Not all browsers support this for XMLHttpRequest initiated transactions though. Mozilla appears to have recently got support for it but IE does not. Alex Russell points to a Microsoft Support article that provides another means to do the same sort of thing but then you have to have two data formats depending on which method you are using.
Even if multipart/x-mixed-replace was the tool of choice there is one further problem with persistent connections. Most (if not all) web browsers only have a limited number of connections it uses for HTTP requests. Internet Explorer only uses two for example. This means if you use one for a persistent connection then all other requests only go through the single connection. If you load another page that uses a persistent connection then you're stuck. No more HTTP requests can be made. This pretty much kills the idea of keeping the connection persistent for general use, and is another reason why my previous post closed the connection between events.
In fact, I've since changed the example (not yet available for download) so that it closes the connection after a set timeout as well, to allow other HTTP requests to be processed. I was having problems with using Backbase whereby some of its server requests were blocking due to the persistent connection being around.
I've done some research over the last couple of days and found a third possible option. Flash allows persistent connections to the server via its XMLSocket class. It is also possible to communicate between the browser and an embedded flash application via Javascript. This would allow writing a small flash application that did nothing but make the connection to the server and then Javascript is used for sending and receiving events across that connection.
This has the advantage of using a different connection pool that the browsers, and you can use any protocol. The disadvantage is that XMLSocket can only connect to ports numbered greater than 1024 and it is not tunneled over HTTP so could be blocked by a firewall. But if the firewall issue is not a problem then it would be possible to write a small Erlang tcp server that communicated across that socket and to the browser.
Backbase actually does something very similar for its charting controls. These controls are embedded flash with the data sent to the control using Javascript from the browser. It does not use a socket connection to the server however.
Another library that does similar is the Canvas object in Nevow. That library embeds a flash object in the page which is used for displaying vector graphics. It makes a connection to the server and allows the server to update the canvas as desired via communication over that socket.
The best general library for doing this sort of thing would seem to be the AFLAX library. This amazing library allows calling any Flash library call from Javascript. Unfortunately it's Flash 8 only and that version of Flash is not yet available for Linux as far as I'm aware.
What I plan to do is write a small flash application to embed to do the server connection and explore using that for the server push events. As a fallback I can have the library use XMLHttpRequest if there is a problem due to firewall restrictions. The final fallback could be an IFRAME if the browser doesn't support XMLHttpRequest.