/    Sign up×
Community /Pin to ProfileBookmark

Facebook-like Push State

Ok, with the app that I’m developing now, I know I need to learn how to do this.

You know when you’re just looking at somebody’s wall or something, on facebook and all of a sudden a comment just appears? I’m assuming this is because facebook pushes it to the browser and they don’t appear to do it with continuous server polling. How does facebook do this?

I understand they have a lot more resources than I am likely to have, so if I can’t do it the same way they do, how can I mimic this?

to post a comment
JavaScript

34 Comments(s)

Copy linkTweet thisAlerts:
@svidgenMar 08.2012 — See Comet.

If you're doing this with PHP on the backend, you'll probably want to write a daemon to ferry messages around -- possibly even handle the "pushes" itself, or maybe have your scripts poll against common memory objects (maybe use an APC store), or you'll find yourself hitting the database pretty hard, possibly DOSing yourself as soon as a handful of folks are connected.
Copy linkTweet thisAlerts:
@svidgenMar 08.2012 — Attached image is an example of facebook's Comet-like polling as viewed through Chrome's network activity monitor.
Copy linkTweet thisAlerts:
@rnd_meMar 09.2012 — comet is soooooo last year. what a waste of http requests and ferrying cookies around every 20 seconds. some of us are not on unlimited data plans or using battery cases...

look into websockets and eventSource.

fallback to xhr2 /http1.1 chunked long-poll for IE8+9, jsonp long-poll for everyone else.

socket.io makes it trivial, if your server is one of the ones it supports.

if you have to code you own, i would recommend using it just to raise custom events on the client, and using ajax to fetch the updated data.

this let's you re-use cached transactions to do the heave lifting if you have more than a few hundred bytes of data.

-code client events like newCalendarItem(1234,"20120704T2100","Fireworks!"), and sideBarUpdate(1235, "news", "Election results published");

-raise those events using comet/sockets/eventSource

-use the event code to update your app UI and data cache


[CODE]
<!--[if lte IE 7]><script type='text/javascript' src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script><![endif]-->
<script>
function sideBarUpdate(id, cat, title){

//cache index for later or composite views:
App.cache.sidebar[id]=[cat,title];

//warm-up item page, cache in http pool for offline viewing:
new Image().src="/"+cat+"/article_"+id;


//grab all the article tags from the sidebar:
var barItems=( document.querySelectorAll || window.jQuery )("#sidebar .articles article");

//remove the last one on the list.
var last= barItems[barItems.length-1];
last.parentNode.removeChild(last);

//add the new one at the top:
var art=document.createElement("article");
art.innerHTML=title.link("/"+cat+"/article_"+id);
barItems[0].parentNode.insertBefore(art, barItems[0] );
}
</script>[/CODE]


its temping to be lazy and tightly-couple everything to short the code, but trust me, that's a bad idea in such a rapidly changing environment, and event-driven programming as a model results in better scalability and UI.
Copy linkTweet thisAlerts:
@svidgenMar 09.2012 — ... what a waste of http requests and ferrying cookies around every 20 seconds. some of us are not on unlimited data plans or using battery cases...[/QUOTE]

While websockets [I]may[/I] be a better solution, if they were widely supported, it's a little silly to claim that long polling and other comet-like techniques are the sort of plague you're suggesting they are. A typical site these days has a payload of around 350kb to 1mb and makes around 50 to 100 requests during the initial load. Even yahoo.com -- yes Yahoo, the folks that effectively lead the crusade against large sites that copious unnecessary https requests -- comes with an initial payload of over 600kb and 73 requests.

Now, consider a long-polling JSONP "connection" that re-establishes itself every 30 seconds over the primary domain, resubmitting all cookies (and other headers) with each re-connect. You're looking at about 600 bytes / reconnect, 1.2k/minute. To match the initial payload of yahoo.com in terms of "wasted requests", you need to be connected to the site for 500 minutes -- that's 8.3 hours.

So, you show up to work in the morning, connect to facebook, and if by the end of the day you've gotten no real data through the pipe, you've still only transferred 600kb of "overhead" to maintain your connection.

Not ideal, of course. But, certainly not the plague you're suggesting it is ...
Copy linkTweet thisAlerts:
@rnd_meMar 09.2012 — While websockets [I]may[/I] be a better solution, if they were widely supported, it's a little silly to claim that long polling and other comet-like techniques are the sort of plague you're suggesting they are.

Now, consider a long-polling JSONP "connection" that re-establishes itself every 30 seconds over the primary domain, resubmitting all cookies (and other headers) with each re-connect. You're looking at about 600 bytes / reconnect, 1.2k/minute. To match the initial payload of yahoo.com in terms of "wasted requests", you need to be connected to the site for 500 minutes -- that's 8.3 hours.

So, you show up to work in the morning, connect to facebook, and if by the end of the day you've gotten no real data through the pipe, you've still only transferred 600kb of "overhead" to maintain your connection.

Not ideal, of course. But, certainly not the plague you're suggesting it is ...[/QUOTE]


im not saying they are the plague, im saying there are much better widely-supported solutions available.

2/3 visitors to our site at work arrive in websockets capable browsers. that's pretty wide, don't you think? 2 out of 3 ain't bad! sockets don't crash firebug if left open, which is nice.

the pages on this forum carry about 1.5kb of headers, and one should request every 20 seconds to avoid proxy timeouts, so X6 to your bandwidth calculations.

i was more concerned with battery life. 3g circuits stay on for 15 seconds after last activity, and burn a lot of battery while active. if you are spending 15 of every 20 seconds in active network state, your battery goes from standby life to 1.333X talk life to do nothing else...


i've used both, and i can say the while the user experience may be approximate with both, under the hood real sockets is much faster, lighter on both ends, and has few fewer side-effects than other comet techniques suffer such as cache stuffing, unwanted progress-bar activity, debugger net-tab overflow/shutdown, high mobile network utilization, and additional http traffic on the server. if you have 500 users connected and you send a comet update, you instantly have 500 incoming http requests. it's like a personal miniaturized DOS attack that will own poorly written DB code.
Copy linkTweet thisAlerts:
@aj_nscauthorMar 09.2012 — I was looking at websockets and socket.io, actually. What is the server architecture that is used for socket.io?

It looked like I could only do it with node...which brings me to another question...can I have a node server run alongside a regular apache server? How would node get the updated events - would the node server poll the database and push an event down the socket when it receives a change?

Sorry if I'm way off base here, I'm super new to this and I've realized I'm going to require information on not only the client but also the server side of things as well.

Thanks very much for both of your help so far.
Copy linkTweet thisAlerts:
@svidgenMar 09.2012 — im not saying they are the plague, im saying there are much better widely-supported solutions available.

2/3 visitors to our site at work arrive in websockets capable browsers. that's pretty wide, don't you think? 2 out of 3 ain't bad! sockets don't crash firebug if left open, which is nice.

the pages on this forum carry about 1.5kb of headers, and one should request every 20 seconds to avoid proxy timeouts, so X6 to your bandwidth calculations.

i was more concerned with battery life. 3g circuits stay on for 15 seconds after last activity, and burn a lot of battery while active. if you are spending 15 of every 20 seconds in active network state, your battery goes from standby life to 1.333X talk life to do nothing else...


i've used both, and i can say the while the user experience may be approximate with both, under the hood real sockets is much faster, lighter on both ends, and has few fewer side-effects than other comet techniques suffer such as cache stuffing, unwanted progress-bar activity, debugger net-tab overflow/shutdown, high mobile network utilization, and additional http traffic on the server. if you have 500 users connected and you send a comet update, you instantly have 500 incoming http requests. it's like a personal miniaturized DOS attack that will own poorly written DB code.[/QUOTE]


Well no, I wouldn't call 66&#37; "widely supported." For no other web technology would I make a recommendation based on 66%. For websockets, you can certainly make a case -- if you truly have a very low inter-visitor latency requirement, you can tell the other 33% to buzz off or that their experience will be less than great.

And I wouldn't go down the path of pretending that websockets yield any significant battery life savings. If you're correct, 3g circuits stay active for 15 seconds after activity, and this is a huge battery drain, you're still making the huge and peculiar assumption that your visitors will open your site, log in, and sit there completely idle for hours on end -- doing nothing else at all that would activate their radio -- AND that the mobile device will be configured NOT to sleep after a few minutes of idle time.

That's just silliness, if you ask me. Battery life is no reason to use websockets.

Given the slow-adoption of websockets by Microsoft, leaving 33% of users unable to take advantage, and given the additional complexities associated with a websocket solution as compared to the ultra-trivial JSONP client poll or even a long poll, I'd say the best practice for most applications is still to start with the simple solution and "upgrade" to websockets if necessary.

And probably the biggest and best case I can make against building any new app with websockets: I've seen no other major app that uses websockets -- all the big, successful companies still use long-polling. Consider Facebook and Google (gmail, docs, google "instant") -- apps that maintain more simultaneous connections than any other on the net without websockets. In fact, the only place I have seen websockets are on demo/experimental pages for web sockets!

To be clear though, I'm not suggesting either solution is necessarily good while the other is bad. They serve specific purposes. Websockets are appropriate for applications that require ultra-low latency intra-user messaging: web-based remote desktop clients, real-time action-like games, audio/video streaming, life-critical health monitoring interfaces, etc.

News feeds, comment feeds, chatrooms ... not great candidates for websockets, IMO. Google and Facebook seem to agree.

That said, if you're interested in websockets for learning purposes, or if you're one of the 0.001% who really "need" a web app with a stateful, full duplex connection to a dedicated application server, take a look at socket.io, as rndme suggested: it provides the client and server functionality (via node.js).

If it were me, I'd write a my socket server in C or PHP. Maybe start by looking here: http://code.google.com/p/phpws/ (looks like an active project)


... but really, I'd avoid using websockets for any practical application unless they were absolutely necessary or significantly cost-saving. No sense investing the time for 66% of your visitors when an older, less efficient method will suffice.
Copy linkTweet thisAlerts:
@meon113Mar 09.2012 — wow, that code is so nice. I think I would try that one. how about using java scripting and php combined with ajax?

[url=http://www.moenkitchenbathfaucets.com/]moen bathroom faucets[/url] | [url=http://www.moenkitchenbathfaucets.com/]moen shower faucets[/url]
Copy linkTweet thisAlerts:
@svidgenMar 09.2012 — I was looking at websockets and socket.io, actually. What is the server architecture that is used for socket.io?

It looked like I could only do it with node...which brings me to another question...can I have a node server run alongside a regular apache server? How would node get the updated events - would the node server poll the database and push an event down the socket when it receives a change?

Sorry if I'm way off base here, I'm super new to this and I've realized I'm going to require information on not only the client but also the server side of things as well.

Thanks very much for both of your help so far.[/QUOTE]


I don't think you can bind to a port that's being use by another application. So, unless you're running your whole site with node, you can't use node for your websocket over port 80. But, you should just as easily be able to use port 8080 (or whatever) for your websocket connection.

In terms of the actual inter-user messaging, I think you can be creative here. I haven't written anything with node, so I'm being a little speculative here, but I think it's a stateful server application. You're effectively writing the web server itself (most of the work is done for you, of course). But, that means you can create pan-connection variables, message queues, etc. So, polling the database shouldn't generally be necessary -- not with a websocket server, and ideally not even with a good long-polling daemon.

The same would be true if you write a websocket server in PHP: you'd be writing an application that has a common state shared by all active connections. It's up to you to keep track of and ferry messages where they need to go however you can ... probably in a "shared" memory structure.
Copy linkTweet thisAlerts:
@rnd_meMar 09.2012 — Well no, I wouldn't call 66&#37; "widely supported." For no other web technology would I make a recommendation based on 66%. For websockets, you can certainly make a case -- if you truly have a very low inter-visitor latency requirement, you can tell the other 33% to buzz off or that their experience will be less than great.
[/QUOTE]


wow, wait a second there. i never said to only use sockets. Im saying that it should be the primary method since it's the best and most browsers support it.

all the other comet techniques are a hack.

im suggesting that he use web sockets if available and fallback to xhr2 long-polling for IE, and jsonp long polling for anything else with unknown support. socket.io has a 5-method stack, but for hand-coded servers, the 3 mentioned are enough for 100% coverage.


if you have some data showing that long-polling and sockets have similer battery life, i'd love to see it. The problem with polls on mobile is that they never let the phone sleep. With sockets, all the data arrives as it comes. there are no regular pings, and no extra connections per-event.

I'm simply reporting what i've found in an anecdotal fashion, and attempting to explain my observations with a hypothesis based upon the principles of cell communication as laid out by ATT. It's a lot of work setting up and tearing down an http connection compared to dripping a few bytes from the socket server.
Copy linkTweet thisAlerts:
@aj_nscauthorMar 09.2012 — I don't think you can bind to a port that's being use by another application. So, unless you're running your whole site with node, you can't use node for your websocket over port 80. But, you should just as easily be able to use port 8080 (or whatever) for your websocket connection.

In terms of the actual inter-user messaging, I think you can be creative here. I haven't written anything with node, so I'm being a little speculative here, but I think it's a stateful server application. You're effectively writing the web server itself (most of the work is done for you, of course). But, that means you can create pan-connection variables, message queues, etc. So, polling the database shouldn't generally be necessary -- not with a websocket server, and ideally not even with a good long-polling daemon.

The same would be true if you write a websocket server in PHP: you'd be writing an application that has a common state shared by all active connections. It's up to you to keep track of and ferry messages where they need to go however you can ... probably in a "shared" memory structure.[/QUOTE]


Thanks, I'm just trying to get my head around this kind of programming. What I was thinking was to keep my current application served up through apache without modifications. 'Actions' performed by the user would be sent via routine ajax request to some php script on the server that updates something in the database. I had then considered using a websocket (or similar) to listen to a node server on 8080 that 'hears' this action (probably through database polling) and sends whoever is listening a notification.

Now that I just typed all that out, I'm thinking it would be easier if all actions that were performed were sent through node to the database rather than through a regular php script on apache - but I'm thinking that would require a major change in the backend of the application that I can't justify at this point.
Copy linkTweet thisAlerts:
@rnd_meMar 09.2012 — I was looking at websockets and socket.io, actually. What is the server architecture that is used for socket.io?

It looked like I could only do it with node...which brings me to another question...can I have a node server run alongside a regular apache server? How would node get the updated events - would the node server poll the database and push an event down the socket when it receives a change?
[/QUOTE]


you can do it with node along side apache on a different port, or even node on a VPS halfway across the world.

socket.io reports support for the following languages: Erlang, Java, Lua, Perl, Go, Python, Ruby, Flash, though i've only ever use it in node.

Part of some of my socket code is like this:
[CODE]App.broadcast=function(strEventType, varData){
io.sockets.emit(strEventType||"error", varData || null);
};
// ...
fs.watchFile( path, function (curr, prev) {
if(curr.mtime-prev.mtime && curr.size >1 ){
App.broadcast("fileModified", path);
}//end if changed?
});//end watchFile callback
[/CODE]


This raises an event on all clients within a second :: fileModified("./autoexec.bat") :: whenever the file is changed.

to actually talk from apache to node, i would use a small flat file and watch it in node, as above. you can broadcast the event when the file changes, you don't even need to load the file, just use it as an inter-process signaling device via it's mod date.

other options include environment variables, DBs, nosql, process signaling, and pinging node via http from php or apache.


there are 15-lins socket.io chat rooms. It would be perfect to sit alongside an existing app for use a signalling subsystem, if you have the 12-20MB of ram available, which most do.
Copy linkTweet thisAlerts:
@svidgenMar 09.2012 — all the other comet techniques are a hack.[/QUOTE]

Well yeah. The web is a hack in general ... So what?


im suggesting that he use web sockets if available and fallback to xhr2 long-polling for IE, and jsonp long polling for anything else with unknown support. socket.io has a 5-method stack, but for hand-coded servers, the 3 mentioned are enough for 100% coverage.[/QUOTE]

I'll recommend the solution that works cross browser in itself long before I recommend leaning on a compatibility library. That takes the hackery to another level in itself. Even if you link to that library on the maintainer's remote server (which in itself is a security hole), you're at the mercy of their ability to keep up with the changes across browsers.

It's far less hacky to use a "hack" that we all know works in [I]every[/I] browser build over the past 10 years.


if you have some data showing that long-polling and sockets have similer battery life, i'd love to see it. [B]The problem with polls on mobile is that they never let the phone sleep.[/B] With sockets, all the data arrives as it comes. there are no regular pings, and no extra connections per-event. [/QUOTE]

That's absurd. If anything, an active websocket will keep your mobile device awake. Your mobile device will take the first chance it can to fall sleep after it's idle timeout (which is based on use activity, not network activity). So again, if anything, long-polling will give your device a brief window to fall asleep in. An open socket connection will not allow this (if the device is respecting network connections -- which I doubt).

I'm simply reporting what i've found in an anecdotal fashion, and attempting to explain my observations with a hypothesis based upon the principles of cell communication as laid out by ATT. It's a lot of work setting up and tearing down an http connection compared to dripping a few bytes from the socket server.[/QUOTE]

Ok. Though, if the target audience is 3G clients, most users will be using a native app anyway. If your site doesn't come in app-form, folks will find something similar that *does* come in native-app form. One thing they *won't* to do is log into your site and then just sit there, doing nothing else but wait for updates from your app ... Absolute silliness.

Again ... websockets have uses -- no way is perserving battery life one of them.
Copy linkTweet thisAlerts:
@svidgenMar 09.2012 — Thanks, I'm just trying to get my head around this kind of programming. What I was thinking was to keep my current application served up through apache without modifications. 'Actions' performed by the user would be sent via routine ajax request to some php script on the server that updates something in the database. I had then considered using a websocket (or similar) to listen to a node server on 8080 that 'hears' this action (probably through database polling) and sends whoever is listening a notification.

Now that I just typed all that out, I'm thinking it would be easier if all actions that were performed were sent through node to the database rather than through a regular php script on apache - but I'm thinking that would require a major change in the backend of the application that I can't justify at this point.[/QUOTE]


Well, if you already have (or are more prepared to have) PHP dumping things into a database and you just need an efficient way to distribute the updates, having a single process handle that is going to be better. Even if you were long-polling, you wouldn't want to have 1000 (or even 10) client connections with PHP threads all hitting the database several times per second. You want ONE thread hitting the database several times per second.

OR ... you use the database primarily as a historical record. Perform all your message delivery with shared memory. Or, dump the historical record into the database and then connect to your websocket service and deliver a copy of the message there (well, I'd send the live copy first, if low latency is a high priority).

I'd venture to say the guts of your inter-client messaging system should look the same regardless of whether your messages are going out over websockets.
Copy linkTweet thisAlerts:
@rnd_meMar 09.2012 — 
OR ... you use the database primarily as a historical record. Perform all your message delivery with shared memory. [/QUOTE]


how do you do that in PHP, all the php chats ive seen use a DB or flat file to pass messages between client's back-end processes.
Copy linkTweet thisAlerts:
@svidgenMar 09.2012 — how do you do that in PHP, all the php chats ive seen use a DB or flat file to pass messages between client's back-end processes.[/QUOTE]

My knowledge of it is theoretical for the moment, but there's no reason you wouldn't be able to use something like http://php.net/manual/en/book.apc.php

In that case, you still end up "polling" a shared object for changes, and you have to deal with locking issues, probably using apc_inc and apc_dec to for a semiphore-like mechanism. But, this ought to be a lot more efficient than polling the database from N different threads.

Another option is to set up a daemon -- which can be used to handle both websocket requests and local inter-long-poll-connection messages. PHP request connects over local socket to daemon, which holds the connection open until a message arrives *or* a timeout occurs.

Both options are likely to be more efficient than hitting the database thousands of times per second -- even if you're only hitting a MEMORY table.
Copy linkTweet thisAlerts:
@svidgenMar 09.2012 — Both options are likely to be more efficient than hitting the database thousands of times per second -- even if you're only hitting a MEMORY table.[/QUOTE]

... which, if you do need want to use the database for this, you'd clearly want to be using a MEMORY table. And you'd want to keep it small, flush stale records frequently, and keep your queries short and simple. Not too different than just using shared memory, except for the overhead involved in reconnecting to the database (if necessary), re-transmitting the query, and receiving a response -- which is usually empty anyway.
Copy linkTweet thisAlerts:
@svidgenMar 09.2012 — how do you do that in PHP, all the php chats ive seen use a DB or flat file to pass messages between client's back-end processes.[/QUOTE]

Sorry for the repeated posts ... But, I figured I should mention ...

It's tough to find efficient PHP samples that accomodate high load. Damn near everyone on the planet writes PHP. Doesn't mean they know much of anything about application development, best practices, or even basic CS principles.

And bear in mind, most sites can get away with a horribly inefficient solution (mine certainly can). A trickle of 10 or 20k daily users can be dealt with by throwing more hardware at the problem -- which is what most companies do before the question the competency of their developers.
Copy linkTweet thisAlerts:
@rnd_meMar 09.2012 — @svidgen:

i love you man, but you're being a negative nancy. i can tell you've not used socket.io because

1) you're wrong about implementation details

2) you're not singing it's praises from the mountain tops

i'll admit i was sceptical at first as well, but when i got to use it, I was like "OMMFG, i've been wanting this for years, and now its 2 lines of code!".

i have never heard of anyone going back to polling after using socket.io...
Copy linkTweet thisAlerts:
@svidgenMar 09.2012 — @svidgen:

i love you man, but you're being a negative nancy. i can tell you've not used socket.io because

1) you're wrong about implementation details

2) you're not singing it's praises from the mountain tops

i'll admit i was sceptical at first as well, but when i got to use it, I was like "OMMFG, i've been wanting this for years, and now its 2 lines of code!".[/QUOTE]


LOL ... ok. I did explicitly state lack of hands-on experience with socket.io and node.js. In fact, I'd say my primary argument was this:

And probably the biggest and best case I can make against building any new app with websockets: I've seen no other major app that uses websockets -- all the big, successful companies still use long-polling. Consider Facebook and Google (gmail, docs, google "instant") -- apps that maintain more simultaneous connections than any other on the net without websockets. In fact, the only place I have seen websockets are on demo/experimental pages for web sockets![/QUOTE]

websockets are currently only being used by students, "adventurers", and elitists. Perhaps you're privy to a large-scale application that's using them, but all the big players I'm aware of are sticking with the old tricks. And in general, it's good to follow suit: You can be sure Google and Facebook will start using websockets the [I]microsecond[/I] it's advantages outweigh the cost.


[B]ADDENDUM:[/B] That said, if you're working on an educational project or a "novel" idea that can only be accomplished with websockets, have at it. But, I couldn't justify the technology in a "real" application for another 3 to 6 years. My supervisor sure as hell wouldn't go for it -- even if I assured him that the 33&#37; will be taken care of with fall-back mechanisms. He'd say, "No. We need to use a well-established solution for which we're familiar with the scalability, reliability, and security issues. Let someone else test the new technology for awhile. We'll pick it up when Google or Microsoft are using it." Or maybe more simply, he might just say, "why not use the solution that doesn't need a fallback?"
Copy linkTweet thisAlerts:
@rnd_meMar 09.2012 — But, I couldn't justify the technology in a "real" application for another 3 to 6 years. My supervisor sure as hell wouldn't go for it -- even if I assured him that the 33&#37; will be taken care of with fall-back mechanisms. He'd say, "No. We need to use a well-established solution for which we're familiar with the scalability, reliability, and security issues.[/QUOTE]

socket.io is more than just websockets, it's homogenized comet with the cherry of websockets on top. One event interface to code once, instant unit-testable support from Chrome 20 - IE6.

using a package like socket.io ensures you are kept abreast of any performance or security concerns asap. There are dozens of people working on socket.io, many of them at least as smart as us, and all are way more experienced in the specific domain than either of us. to update, you go to the command line and type:
[CODE]npm update socket.io[/CODE]

and you're fixed. That nasty bug in BrowserX v 12.345 without flash behind a proxy server that blah blah blahs when you refresh a page while a long-poll is in the process of re-connecting, taken care of. that's made up, but there are TONS of weird scenarios out there. Socket.io abstracts everything to such a high level it's like you're hanging out with lindsy lohan.

It's not much of an exaggeration to say that each browser and indeed each major version of each browser needs it's own slightly different handling for any kind of comet. One man alone cannot build a reliable and user-friendly delivery mechanism under all the different conditions to support the transports around before sockets in even just the top 5 user agents.


yeah, you can use jsonp to do something like what socket.io does, but it doesn't have the clean programming interface, invisible client operation, smart error-handling, and lack of proxy/browser-cache/browser-version quirks.

In short, socket.io makes it easy and safe to do, makes you look like a pro to clients and a pimp to all those firebuggers out there.
Copy linkTweet thisAlerts:
@svidgenMar 09.2012 — Well, I certainly agree that for operations wherein most browsers support *some* mechanism, a compatibility library is nice to have. But, I wouldn't depend on it for anything business critical.

Well before anyone heard anything about AJAX or comet, there were two hacks that a few developers here and there used for push-like asynchronous communications. POSTs to hidden iframes, and dynamically added script tags. Both techniques worked on all major browsers back then, both still work today. And in some cases back in the day, you might have even seen some long-running requests, seemingly to facilitate push-like updates. No one called it Comet or MagicJavaScriptListen or whatever else -- it was just something that worked, so we used it. We didn't need compatibility libraries or latest-version browser updates to do this, and we still don't.

Yes, better solutions are here-ish, but they're young and they're lacking in reach. Like many other developers, I'm eager to play with them as I have time, but I'm not going to leap to depend on young technologies, yet to be widespread, [I]or[/I] 3rd party libraries, ingrained with layers of conditionals, functionality sniffs, and thousands unnecessary possible points of failure.

I have a solution already works everywhere I need it to, with no modifications or special cases, and a very small set of possible failure points.


[B]It is good that some folks, like yourself, are willing to push the bounds and use new "things" tho.[/B] Without that push, browser vendors aren't pressured to accommodate our visions or jump on board with experimental or budding technologies, protocols, standards, etc.. For business purposes, I'm not one of those folks tho -- and I wouldn't recommend pushing the bounds to anyone outside of academic and bloggy "look how cool this is" environments.
Copy linkTweet thisAlerts:
@svidgenMar 09.2012 — Sorry for hijacking your thread, aj_nsc ...
Copy linkTweet thisAlerts:
@aj_nscauthorMar 09.2012 — Sorry for hijacking your thread, aj_nsc ...[/QUOTE]

No apologies necessary, love the argument, err....discussion going on here. I never knew much about any of this kind of programming and I'm interested in hearing different points of view on it.
Copy linkTweet thisAlerts:
@rnd_meMar 09.2012 — Well, I certainly agree that for operations wherein most browsers support *some* mechanism, a compatibility library is nice to have. But, I wouldn't depend on it for anything business critical.[/QUOTE]

i don't think sidebar updates are "business critical". isn't that taking it to 11 just a bit here? would you depend on js itself for anything "business critical"?

i like debate, but let be reasonable towards the OP here.


what is your arguments here, that socket.io doesn't work, or that jsonp polling is somehow better?


if you are saying socket.io doesn't work everywhere, can you name a browser that supports any comet that doesn't support socket.io?


are you saying old-school polling is more, well, more better?

i guess im not sure what you're argument is, but socket.io bundles 10 years of comet experience into a clean api that works in IE5.5. The old jsonp technique is indeed used by socket.io if nothing better is available.

if it makes you feel any better, you can disable websockets and flash and just use ajax and jsonp comet with socket.io. how that's better i don't understand...
Copy linkTweet thisAlerts:
@svidgenMar 09.2012 — Oh, I'm just saying that right now is not the time to implement your server-interactions with websockets [or any other bleeding edge technology] or any 3rd party libraries that attempt to juggle variations in browser compatibility -- even if they appear to succeed at doing so. If that sort of thing was acceptable in a business setting, [I]successful businesses[/I] would be doing it. (And they're not.)

Who [B][I]is[/I][/B] doing it? Well ... folks like you are. And that's how it ought to be. Folks who want to experiment with the bleeding edge stuff, see how it can be used, write proof of concepts, stress and security test the technology, etc.. But, not businesses. And not for applications that need predictable security, performance, and stability.

It may very well be that the current websocket protocol is perfect, that socket.io is rock solid, that browser variations [B]won't[/B] throw us for any loops, etc. But, the only way to gain some certainty on that matter, the only way to justify using new technologies wherein N people's jobs' depend on 99.99% uptime is to let a lot of folks like yourself try the stuff out and report back. Until then, applications whose security, performance, and stability affect revenue and jobs should be written using proven patterns, even if those patterns are hacks or inefficient -- they're [B]predictably[/B] inefficient and hacky; new patterns are not.
Copy linkTweet thisAlerts:
@svidgenMar 09.2012 — i don't think sidebar updates are "business critical". isn't that taking it to 11 just a bit here? would you depend on js itself for anything "business critical"?[/QUOTE]

On that specific point, I'm not intending any hyperbole. Maybe the technology is used to update a sidebar, maybe it's use to deliver a person-to-person message, maybe it's used to update the status image next to someone's name, etc. I can't tell you whether "sidebar updates" are business critical for *your* business.

But, if FB's updates start to get sketchy, people start signing off. So ... yeah, for some folks, sidebar updates are business critical.
Copy linkTweet thisAlerts:
@svidgenMar 09.2012 — how do you do that in PHP, all the php chats ive seen use a DB or flat file to pass messages between client's back-end processes.[/QUOTE]

If you're interested (presumably on a purely academic level), I've written a very brief proof-of-concept using APC to support long-polling jsonp. There's no locking in place yet, but here are the basics:

Note: these run in the context of a driver script that manages output buffering, URL rewrite mapping, page theming, setting cache headers, etc. The theme that handles these scripts just looks for $json_response (string) and submits them to the callback function -- all other output is ignored.

receive.inc
[code=php]<?php

// tell the driver script to send all necessary no-cache/expires headers
$do_not_cache = true;

// get ready to listen
$timeout = 30;
$starttime = time();
$channel = isset($_GET['channel']) ? substr($_GET['channel'], 0, 16) : "general";
$last_received = isset($_GET['last']) ? (int)$_GET['last'] : 0;


while ($starttime + $timeout > time()) {

$mq = apc_fetch($channel);
if ($mq && is_array($mq)) {
$rv = array();
foreach ($mq as $m) {
if ((int)$m['id'] > $last_received) {
$rv[] = $m;
}
}

if (sizeof($rv) > 0) {
$json_response = json_encode($rv);
return 1;
}
}


// wait 15ms before checking again
usleep(15000);

}

// timeout.
$json_response = "null";

?>
[/code]



send.inc
[code=php]<?php

$do_not_cache = true;
$channel = isset($_GET['channel']) ? substr($_GET['channel'], 0, 16) : "general";
$message = isset($_GET['m']) ? $_GET['m'] : '';


// acquire next ID
if (!apc_exists($channel . "_message_id")) {
apc_store($channel . "_message_id", 1);
$m_id = 1;
} else {
$m_id = apc_inc($channel . "_message_id");
}


// acquire the queue
$mq = apc_fetch($channel);
if (!$mq || !is_array($mq)) {
$mq = array();
}


// purge old messages using an arbitrary max message value for now (128)
foreach ($mq as $k => $v) {
if ($v['id'] < $m_id - 128) {
unset($mq[$k]);
}
}


// add the new message
$mq[] = array(
'id' => $m_id,
'message' => $message
);


// store the new array in the cache.
// the TTL probably isn't necessary here ...
apc_store($channel, $mq, 30);


// return success ...
print "messageSent();";

?>
[/code]


Again, no locking mechanism is currently in place. It needs some apc_inc/apc_dec action to simulate semaphores and/or a key-based writelock mechanism -- not too tough to implement either way, I think.
Copy linkTweet thisAlerts:
@rnd_meMar 09.2012 — Oh, I'm just saying that right now is not the time to implement your server-interactions with websockets [or any other bleeding edge technology] or any 3rd party libraries that attempt to juggle variations in browser compatibility -- even if they appear to succeed at doing so. If that sort of thing was acceptable in a business setting, [I]successful businesses[/I] would be doing it. (And they're not.)[/QUOTE]

" any 3rd party libraries that attempt to juggle variations in browser compatibility" , you mean like jQuery? A lot of businesses use that for ajax, some of them even make money.

related, i don't think we should look for big business for idea on how to do web. 68% of fortune 500 companies use sharepoint, need i say more?

If you view the source of a website of just about any successful business, chances are you'll find terrible html, all sorts of proprietary meta tags and hacks, several analytical packages competing, etc.

google.com, apple.com, and microsoft.com don't even validate, and they are very successful. youtube is doing alright without IE6, even though the site is monetized no longer "universally compatible"...


my goal is to show the OP the simplest, most reliable way to get server-events up and running. socket.io ensures universal compatibility, optimum client machine utilization, and 1SLOC coding of actual event handling.
Copy linkTweet thisAlerts:
@svidgenMar 09.2012 — " any 3rd party libraries that attempt to juggle variations in browser compatibility" , you mean like jQuery? A lot of businesses use that for ajax, some of them even make money.

related, i don't think we should look for big business for idea on how to do web. 68% of fortune 500 companies use sharepoint, need i say more?

If you view the source of a website of just about any successful business, chances are you'll find terrible html, all sorts of proprietary meta tags and hacks, several analytical packages competing, etc.

google.com, apple.com, and microsoft.com don't even validate, and they are very successful. youtube is doing alright without IE6, even though the site is monetized no longer "universally compatible"...


my goal is to show the OP the simplest, most reliable way to get server-events up and running. socket.io ensures universal compatibility, optimum client machine utilization, and 1SLOC coding of actual event handling.[/QUOTE]


Well, on that note, I hate jquery! It's stupid. But, compared to socket.io I'd say it's a lesser evil: it's dealing with a much more predictable set of compatibility issues. That said, I still wouldn't recommend it ... mostly b/c I hate it. It's ugly as sin.

Validation? A stupid and useless "badge" for your site ...

"The simplest and most reliable way to get server-events up and running" ... well if by that you mean, the simplest and most reliable way to get low-latency data from the server, the answer is long polling. Every client supports it without issue. And the server-side component is insanely trivial to implement. Hell ... I effectively just wrote an APC-based "chatroom" engine proof of concept in less than 15 minutes ... what could be simpler than that?
Copy linkTweet thisAlerts:
@rnd_meMar 09.2012 —  Hell ... I effectively just wrote an APC-based "chatroom" engine proof of concept in less than 15 minutes ... what could be simpler than that?[/QUOTE]


one that does the same thing in node (no sockets) that i wrote in 4 mins:

[CODE]
var http = require('http'),
url=require("url"),
bag={};

http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
var q=url.parse(req.url),
k=q.key,
v=q.value;
res.end( "cb(" + JSON.stringify( v ? (bag[k]=v) : bag[k] ) +")" );
}).listen(5555, '127.0.0.1');[/CODE]


yeah i know they are not 100&#37; the same, but mine responds to requests and yours doesn't, so it's a wash feature-wise.

i have 11 mins of dev time to spare if you want me to make it have rooms and message stacks, this is more to show a way of passing messages between clients.
Copy linkTweet thisAlerts:
@rnd_meMar 09.2012 — oh, what the heck, i can't help it:

with rooms, message que delivery and stack management:
[CODE]var http = require('http'),
url=require("url"),
bag={};

http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
var q=url.parse(req.url),
k=q.key,
v=q.value;

//assign v to message array:
if(v){ (bag[k]=bag[k]||[]).push(v); v=bag[k]; } else{ v=bag[k]||[]; }

//limit to 10 stacked messages
v.length=10;

res.end( "cb(" + JSON.stringify( v ) +")" );
}).listen(5555, '127.0.0.1');[/CODE]


now it's comparable to yours.

total dev time: 9 mins.

lots of successful companies use node.js, some of them regular people might have heard of...
Copy linkTweet thisAlerts:
@svidgenMar 10.2012 — Oh, I wasn't knocking node.js. I wouldn't promote it either though, quite yet. I don't know enough about it's history or have any case studies to say anything intelligent about it's security, performance, or reliability. Node intrigues me a great deal, because you can use the same syntax server-side as you can on the client side, which is pretty neat.

In any case, you'll have to explain your example for me. By my read, there are some notable differences (and possibly bugs). But, I'm not a node programmer, so ... I'm probably missing things:

How does it facilitate long-polling. By my read, it looks like it returns immediately.

In the absence of a message, it appears to simply return the messages located at index (room/channel?) k, rather than return only those messages in the channel not yet received by the client.

I also don't understand how the limiting is supposed to work here. If you push v to the end of the array at k and subsequently set a length limit on the array, you're removing the message that's just been put onto the stack.

So, let me be up-front here: I'm interested in how this works, if it does in fact work the same way as my posted scripts. However, if it doesn't provide the same functionality, bug-free, as my posted scripts, I can also claim to have written my messaging system in under 9 minutes (original write-up of both in about 5) ... before some simple optimizations and debugging.

Does it function like my script or not?
Copy linkTweet thisAlerts:
@rnd_meMar 11.2012 — 
So, let me be up-front here: I'm interested in how this works, if it does in fact work the same way as my posted scripts. However, if it doesn't provide the same functionality, bug-free, as my posted scripts, I can also claim to have written my messaging system in under 9 minutes (original write-up of both in about 5) ... before some simple optimizations and debugging.

Does it function like my script or not?[/QUOTE]


i wasn't 100&#37; clear what you were doing with yours to be honest. im more of a front-end coder myself, and php makes me cross-eyed at times. props on using apc. I didn't know about that, and it's going to be useful for a few project i have.


here is a simple demo of socket.io i stitched together for you to rip apart.

i spent all in all about 30 mins on this, but the extra time was well spent.

It works in ie8, ie9, ie10, opera10, chrome19, FF11, ff3.6 ubuntu, FFmobile, ipad1, ipod touch4, android 2.3 browser, and the Wii.

i don't have old IE handy, but i'd bet it works fine.



the only thing wrong is lack of client UX in IE9+10l; you have to use tab instead of return, but that has nothing to do with the topic at hand. A real event handler would fix it easy peasy, but i've wasted too much time already to fix that and re-test. the messaging functionality works in all system tested.

[CODE]//socket.io "chat room" demo

var App={
ip: "127.0.0.1" //change this to your server ip
},
http = require('http'),
url=require("url");


var PAGE=(function(){/*


<html><head>
<title>chat</title>
<style>
p, input { width: 80%; max-width: 50em; font: 14px monospace;
padding: 2px 4px;
background:#ddd; box-shadow: 1px 1px 3px #888; }

p { height: 12em; overflow: scroll; overflow-x: hidden; }

</style>
</head><body>
<input onchange="sendChat(this.value); this.value=''; this.focus(); "/>

<p>Waiting to connect...</p>

<button onclick="elm.innerHTML='';">clear</button>


<script src="/socket.io/socket.io.js"></script>

<script>

var socket=io.connect('/'),
elm= document.getElementsByTagName("p")[0] ;

function sendChat(txt){
log(txt.italics());
socket.emit("msg", txt);
}

function log(a){
log.r.unshift(new Date().toTimeString().split(/s/)[0].fixed()+ " - "+ a );
elm.innerHTML= log.r.join("n<br />");
if(!a.match(/<i/i)){ document.title="chat: "+a; }
return a;
} log.r=[];


socket.on('msg', log);

socket.on('connect', function (data) {
elm.innerHTML="";
console.log(log('connected.'));
});

</script>
</body>
</html>


*/}).toString().slice(15,-5);
//end HTML ###############################################

// create a server:
var myServer=http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/html'});
res.write( PAGE );
res.end();
}).listen(80, App.ip);



//socket.io stuff:
var io = require('socket.io').listen(myServer);
io.settings['log level']=1; //sshhhh...

io.sockets.on('connection', function (socket) {

socket.on('msg', function (data) {
socket.broadcast.emit( "msg", data);
});

});//end socket bindings
[/CODE]


all you need is a working copy of node, the socket.io package, and the above file.

edit the ip address at the top to your servers and launch: "node chat.js".
×

Success!

Help @aj_nsc spread the word by sharing this article on Twitter...

Tweet This
Sign in
Forgot password?
Sign in with TwitchSign in with GithubCreate Account
about: ({
version: 0.1.9 BETA 6.17,
whats_new: community page,
up_next: more Davinci•003 tasks,
coming_soon: events calendar,
social: @webDeveloperHQ
});

legal: ({
terms: of use,
privacy: policy
});
changelog: (
version: 0.1.9,
notes: added community page

version: 0.1.8,
notes: added Davinci•003

version: 0.1.7,
notes: upvote answers to bounties

version: 0.1.6,
notes: article editor refresh
)...
recent_tips: (
tipper: @nearjob,
tipped: article
amount: 1000 SATS,

tipper: @meenaratha,
tipped: article
amount: 1000 SATS,

tipper: @meenaratha,
tipped: article
amount: 1000 SATS,
)...