Tuesday, June 6th, 2006
IFrame + Script Tags = Portable Comet
In a recent post, I explain the difficulties of Comet (Streaming/Push) in IE.
IE makes it difficult for two reasons: (a) IE’s XMLHttpRequest component doesn’t tell you anything about the response until the connection has closed - even if you try polling it instead of relying on onReadyStateChange, you’ll still get an empty string (Try it); (B) Okay, switch to plan B and inspect IFrame content - we can’t rely on onload, which is only called once at the end, so we *must* poll. But no, polling won’t help either, as the IFrame content remains empty until (you guessed it) the connection is closed. (Try it).
Fortunately, there *is* a portable solution, demonstrated here.
The portable solution is this: Have the server continuously output script tags that call a known function in the parent frame. When you set the child IFrame’s source to point to this service, it will start evaluating the inline scripts as they pop out of the server.
Of course, none of this is really new, at least not to some people. Ajax pioneer Brent Ashley points out:
The ReadyState 3 issue that Michael talks about has been well known (well, apparently not well known) at least since Scott Andrew LePera described the problem in late 2002. It really needs to be fixed.
Hopefully, future versions of IE will expose the ongoing response while the XHR connection is still open. But until then, we at least have a workable technique that works across different browsers.
This area isn’t very well-documented; It would be good to hear what others have done to make streaming portable.













For ICEFaces we are using a heartbeat mechanism that monitors and keeps the connection alive: http://www.icesoft.com/products/icefaces_enterprise.html
OK, this is so 1999. I tried this back then, only problem being that it not scalable in PHP. So I actually reverted it back to a polling mechanism (I just had the hidden iframe reload rather than pause and wait on the server side). Nice that you could use mostly the same code to do it either way, though. But really, it was great holding the socket open in a test environment, and to show how cool it was (in 1999). But to have thousands (tens of thousands, actually) using it is to have that many PHP processes running simultaneously. Blah! Ick! Yuck! $$$!
Sigh. I get tired of this.
One has to remember that the original MSXML parser (i.e. XMLHTTPRequest) was intended to be used in places other than in script–as in C++ and VB, both of which could read IStream objects and actually *do* something with the incoming responseStream or responseBody while it is being filled, both of which represent a stream of bytes which may or may not be complete.
We as part of the scripting community need to remember that not everything is perfectly accessible from script, nor are certain things originally designed to work that way.
Not everything is accessible from script, you know.
And no offense, but you guys *really* need to fix the comment system here. Nothing worse than submitting a comment and ending up at an apparently blank page…
I did some fiddling around with this a while back, trying to do a multi-client chat thing with a broadcast socks server. It worked, but the whole thing is pretty experimental. I tried to explain the technique as well. Enter some junk name and then up your font size. ;)
http://www.schillmania.com/projects/rpc-js/
Pardon the double-comment. Here’s a link directly to the code involved, with some technical explanation.
http://www.schillmania.com/projects/rpc-js/rpc-js.js
I think Google is using a somewhat similar approach with Gmail (as Alex Russell covered several months ago,) and while it works, I think it’s a crazy hack. A technical feat mind you, but still - actually being used in a large-production site? - woah! :)
(Then again, we used to say that about Javascript animation.)
I did something similar, Scott, using a hand-rolled web server that multiplexed connections to avoid running a huge number of CGI processes just to send data out. There was a “control socket” that other local processes could connect to “dispatch” additional data to any one (or all) of the listening clients.
Not everything needs to be done using CGI and stateless HTTP — use HTTP to initiate the connection, (since that’s what the browser talks), but then hand the whole thing off to custom code.
It’s funny how the popularity of the web browsers as an application development environment brings back old problems as new. I think i solved this in 2000. In any case, if you’re using Javeline TelePort or Javeline FrameWork this solution is in there.
[...] Ajaxian has a great little post (”IFrame + Script Tags = Portable Comet“) about IE and Comet and how they don’t play nice together yet. But, they also mention that there is a (hack hack) workaround. It uses IFrame and script tags. [...]
@Tom and @Ajaxian: Yep, they NEED to fix the commenting system… I can’t believe this is still not working properly. That, and the shear volume of worthless posts is getting me pretty close to deleting this feed.
[...] Ajaxian OfficeTheir vision is to be a complete, fully functional MS Office clone on-line. They let you import Excel and Word and other formats into their products. Michael Arrington: You guys have a reputation of [...]
I’m doing this in my C# toolkit, emerge. I accept the requests on a secondary port, and manage the socket IO asynchronously — so no threads are allocated to manage the continous HTTP request. Then I add a reference to the socket into the client’s main context instance, and any processing events automatically flush to the socket if its available (in script tags).
It works great, but I still have to tackle the loading whirl gif of death. That’s why gmail does that subloading Scott — I just have to sort it all out.
anyways, here’s the link to my project, click on the “See It’ and then the Comet tab to see an example in action.
emergetk.com
–ben
Does anyone have any data on server performance with polling vs. comet to push data from a server? On a production system with 100’s of users ould it be better to do an AJAX request every 5 seconds to look for an update from the server or do the iframe hack to keep a connection open? The Comet/iframe method worries me if there are 100’s of open connections to the server that aren’t closing. But at the same time, pounding the server by 100’s of users every 5 seconds doesn’t seem happy either. What are your thoughts on performance between these two methods?
Jeremy,
It depends how the connections are managed. If you are allocating a spare thread for them, then polling will perform better. But if you implement it correctly, with minimal resources allocated, you should be able to keep several thousand sockets open without too much problem.
I haven’t actually done it mind you — but in theory that’s how it should work ;)
Keeping sockets open in Java is much easier to do than, say, PHP, where you are totally out of luck (well, you could use both, I suppose). I’m not sure what Ruby and others provide.
…and you’re all just fine with Ajaxian’s commenting system?
At the very least you could all do your normal post, and then make another post pointing out that the commenting system sucks. I think then they might get it. Maybe. Probably not, it’s been broken forever so why would they fix it now?
Oh well, at any rate I can take comfort in knowing where I can find a completely blank page on the internet. Just gotta make a post on Ajaxian.
This is the exact technique that CGI:IRC uses. It has worked pretty well in most browsers (and it has hardly needed changing since I wrote in late 2002!).
David,
If CGI:IRC is using push, how come i don’t see the loading indication for the lifetime of the page? How did you get around that?
Thanks,
Tal.
One big problem with pushlets (or IFrame and scripts tags) is that the browser (at least IE) reads everything into memory, never releases it and eventually slows down PC to a halt. After all its just one huge page for all it knows.
It may work well for low traffic and/or short-lived sessions, but leave it for a few days or try it on a high volume data stream and you’ll see what I mean.
Gregory - true, however a call to a Javascript function to loop through the DOM to remove those script tags that have arrived from the server should sort that.
Nutz - I don’t remember if I tried it back when I played with this idea, so I tried it again, and alas, it makes no difference in the memory usage. Whether you remove every script tag as soon as it’s processed or not, the memory keeps growing.
I purly love this aproach, but im looking for a demo that uses same connection to send and revice data, is this possible? Anyone seen a example of this?
Im looking for an example:
Explenation:
1.Create a long lived http connection, attach a listener on server side for incoming msg (preferable java or php).
2.Click on a button on the page, that uses the already establish connection and send “hi” to the server, the server responed on the same connection channel with “hello there”.
[...] Ajaxian OfficeTuesday, June 6th, 2006. IFrame + Script Tags = Portable Comet. Category: XmlHttpRequest , Examples , IE , Office , Comet. In a recent post , I explain the difficulties of Comet (Streaming/Push) in IE [...]
Cool, check out my site about home furniture
It’s a fair point…Alex’s original Comet article doesn’t only talk about streaming, but also about a distributed event model (as in Twisted). I guess the JSON-P method is a kind of Comet-lite.
Orbited: http://brbx.com/orbited
Orbited is a comet daemon that works on many platforms for many languages. It supports comet style long-polling as well as Iframe streaming. It also has a clear scaling path.
A small update to this thread.. since a couple of questions on performance came up…
I recently wrote an article on benchmarking comet servers at cometdaily.
This includes some results from benchmarking of Caplin Liberator (http://www.freeliberator.com)
The tests do not specifically put polling up against streaming, but do demonstrate that streaming to thousands of open sockets is not a problem with a well designed server.
Hey,
Great Post…. Good to know…..
Thanks.
http://rndinfo.com