Server-Sent Events: The simplest realtime browser spec
segment.io
segment.io
The only problem with this is c10k - you have to have something writing to the socket and this "something" was basically a process in most cases. It's a great fit for async things like Node or Twisted/Tornado, though. And for Erlang.
Also, unlike WebSockets it's also easy to add SSE support for mobile clients. I've implemented a SSE client class in just over 100 lines of Java, and it's similarly easy to do this with NSURLConnection/NSURLSession on iOS. The W3 standard provides an implementation section that reads like pseudocode.[2]
[1]: https://en.wikipedia.org/wiki/Comet_%28programming%29
[2]: http://dev.w3.org/html5/eventsource/#event-stream-interpreta...
The browser will try hard to keep the connection always on for you (unless instructed otherwise). You don't have to implement your own logic for offline/online detection, exponential backoff, etc. Thanks to id:/Last-Event-Id header the server can make error recovery transparent to the client.
You do need node/tornado/etc to take full advantage of it, but if all you have is PHP or such, then you can still make it real-time-ish. Because SSE automatically reconnects you can have any behavior ranging from a single persistent TCP/IP connection, through Comet, to regular polling. You control this with the `retry:` line and by (not) closing connection on the server (e.g. keep persistent connection when load on the server is low, set high `retry:` and close the connection when the load is high).
http://blog.fastmail.fm/2012/01/09/building-the-new-ajax-mai...
There's a couple of annoying caveats
1. The "retry" nature of the connection isn't quite as reliable as suggested. See the blog post above for more details
2. NAT timeouts. Make sure you have some sort of "ping" either at application or TCP level.
http://blog.fastmail.fm/2013/05/28/push-events-nat-tcp-conne... http://blog.fastmail.fm/2011/06/28/http-keep-alive-connectio...
3. Each SSE connection is regarded as a regular site connection. So if people open up 6 tabs to your site, you might suddenly find your site is unresponsive to users because every available connection is used by an SSE connection. You might need to implement some inter-tab communication system instead.
http://blog.fastmail.fm/2012/11/26/inter-tab-communication-u...
It would be nice to say screw IE users but not everyone can do that.
When it comes to browsers we've still not found a solution that is as solid as Flash sockets; though that could also be a bit of a hangover for us given our reliance on Flash and the subsequent tooling that we have around it.
2 issues; Last-Event-ID is not a header, but a querystring param. Needs 2kb of padding from server before any data.
Looks pretty usable.
(though that polifill didn't work for me for that example, but I didn't spend much time trying to figure out why)
Also, (plug alert) SSE is pretty easy to throw together using https://fanout.io/ and its HTTP streaming data transport, if you want to save yourself from having to set up any new server stuff.
Clients register to listen with the fanout.io CDN, then my app pushes something to the CDN, and fanout.io handles pushing it to all of my end clients?
Can I determine which subset of users receive the message, or is it "all or nothing"? Are clients able to listen on a specific topic/name?
I'd love to get more info, but I didn't see any higher level explanation and don't have time to dive into docs right now.
In the case of HTTP streaming, Fanout acts like a reverse proxy in front of your web server. Incoming requests are relayed to your server, and you can control Fanout's behavior depending on how you reply. For example, you can reply with a "hold" instruction saying to bind the incoming request to streaming channel C. The transaction between Fanout and your server is now complete, while the connection between the client and Fanout remains open. You can then send messages to this client by publishing on channel C.
The process is explained in more detail on this post about our open source reference implementation: http://blog.fanout.io/2013/04/09/an-http-reverse-proxy-for-r...
Implementing something like SSE is just a matter of responding with a stream subscribe with initial response of Content-Type: text/event-stream, and then publishing event chunks using SSE formatting.
Though technically a non-chunked Content-Length-less HTTP/1.0-style response should work too.
Many HTTP servers will not allow you to specify precisely where you break chunks; I would expect that the significant majority of slightly higher level interfaces will not allow you to do that, rather handling buffering themselves.
Many HTTP clients will not allow you to read chunks precisely.
And as for the "event" paramter—well, such things are taken care of in RFC 2616 with chunk extensions; it would end up being
<length of data in hex> ";event=" event-name CRLF data CRLF
e.g. you would replace the following chunk-encoded data (the first and last lines are artefacts of the chunked transfer encoding): 1d␍␊
event: poke␍␊
data: "hey!"␍␊
␍␊
␍␊
with the following: 6;event=poke␍␊
"hey!"␍␊
␍␊
Unfortunately, chunk extensions have never really been used, so I dare say they assessed that technique and decided that it was simply going to require too much work. And so we're left with a new protocol on top of HTTP reimplementing precisely what HTTP already did, but which people forgot about, possibly for performance reasons.And much more effective than DIY. API's are much nicer than old school.
But for production, yea.