Socket.IO and IIS

WebSockets are pretty great. I won't go into too much detail here, but the low-latency persistent connections that WebScokets provide have a temendous potential for boosting many web applications.

Unfortunately, browser support for WebSockets is still spotty, although we've had the basic building blocks for providing WebSocket-like functionality for some time now. Socket.IO patches those building blocks together, and provides WebSocket-like functionality on just about any browser imaginable.

As it turns out, a few servers also don't quite support WebSockets yet. Long story, but until the Windows world migrates to IIS 8, there's also no WebSocket support in IIS. Fortunately, the Socket.IO's Node.js-based server component lets us use AJAX Long Polling to simulate the same functionality, with WebSocket-like semantics. It's not perfect, but it works, and be modified to use actual WebSockets with almost no code changes (once you get a server that supports "real" WebSockets).

In any event, if you're stuck with IIS 7.5, you can still use Socket.IO today. This isn't particualrly well-documented, and there are some needlessly complicated workarounds floating around, so here's how you should do it:

  1. Install Node and iisnode. (More on that here)
  2. In your node application's folder, grab socket.io with npm:
    npm install socket.io
  3. Create your Socket.IO server application, and a client. Be sure to configure Socket.IO with a resource parameter on both your client and server.

Here's a barebones example to get you started. In practice, you'll probably want to use URL rewriting (and Express) so you can also serve up other content.

On the server (myApp/server.js):

var app = require('http').createServer(handler),
io = require('socket.io').listen(app);
io.configure(function(){
io.set('transports',['xhr-polling']); //Use long-polling instead of websockets!
io.set('resource','/myApp/server.js'); //Where we'll listen for connections.
});
app.listen(process.env.PORT);
function handler(req,res){
/*
* Your code for handling non-websocket requests...
* Note that Socket.IO will intercept any requests made
* to myApp/server.js without calling this handler.
*/

}
io.sockets.on('connection', function (client) {
console.log("New Connection");
client.on('message',function(message,callback){
console.log("Message Received");
client.emit('response',"Got it!");
}
}

And on the client (which can be hosted anywhere):

<script src="/path-to-socket.io-client/socket.io.js"></script>
<script type="application/javascript">
var socket = io.connect('http://myServer',{resource: 'myApp/server.js'}); //Same resource as the server. socket.on('response',
function (msg) { console.log("Message received:",msg); });
socket.emit('message','hi');
</script>

In practice, you'll probably want to set up URL rewriting to rewrite requests for anything inside /myApp/* to server.js. In my case, I rewrite myApp/socket to server.js in web.config, and specify myApp/socket as the resource parameter on both the client and server.

← Home