Differences between socket.io and websockets

Misconceptions

There are few common misconceptions regarding WebSocket and Socket.IO:

  1. The first misconception is that using Socket.IO is significantly easier than using WebSocket which doesn't seem to be the case. See examples below.

  2. The second misconception is that WebSocket is not widely supported in the browsers. See below for more info.

  3. The third misconception is that Socket.IO downgrades the connection as a fallback on older browsers. It actually assumes that the browser is old and starts an AJAX connection to the server, that gets later upgraded on browsers supporting WebSocket, after some traffic is exchanged. See below for details.

My experiment

I wrote an npm module to demonstrate the difference between WebSocket and Socket.IO:

  • https://www.npmjs.com/package/websocket-vs-socket.io
  • https://github.com/rsp/node-websocket-vs-socket.io

It is a simple example of server-side and client-side code - the client connects to the server using either WebSocket or Socket.IO and the server sends three messages in 1s intervals, which are added to the DOM by the client.

Server-side

Compare the server-side example of using WebSocket and Socket.IO to do the same in an Express.js app:

WebSocket Server

WebSocket server example using Express.js:

var path = require('path');
var app = require('express')();
var ws = require('express-ws')(app);
app.get('/', (req, res) => {
  console.error('express connection');
  res.sendFile(path.join(__dirname, 'ws.html'));
});
app.ws('/', (s, req) => {
  console.error('websocket connection');
  for (var t = 0; t < 3; t++)
    setTimeout(() => s.send('message from server', ()=>{}), 1000*t);
});
app.listen(3001, () => console.error('listening on http://localhost:3001/'));
console.error('websocket example');

Source: https://github.com/rsp/node-websocket-vs-socket.io/blob/master/ws.js

Socket.IO Server

Socket.IO server example using Express.js:

var path = require('path');
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
app.get('/', (req, res) => {
  console.error('express connection');
  res.sendFile(path.join(__dirname, 'si.html'));
});
io.on('connection', s => {
  console.error('socket.io connection');
  for (var t = 0; t < 3; t++)
    setTimeout(() => s.emit('message', 'message from server'), 1000*t);
});
http.listen(3002, () => console.error('listening on http://localhost:3002/'));
console.error('socket.io example');

Source: https://github.com/rsp/node-websocket-vs-socket.io/blob/master/si.js

Client-side

Compare the client-side example of using WebSocket and Socket.IO to do the same in the browser:

WebSocket Client

WebSocket client example using vanilla JavaScript:

var l = document.getElementById('l');
var log = function (m) {
    var i = document.createElement('li');
    i.innerText = new Date().toISOString()+' '+m;
    l.appendChild(i);
}
log('opening websocket connection');
var s = new WebSocket('ws://'+window.location.host+'/');
s.addEventListener('error', function (m) { log("error"); });
s.addEventListener('open', function (m) { log("websocket connection open"); });
s.addEventListener('message', function (m) { log(m.data); });

Source: https://github.com/rsp/node-websocket-vs-socket.io/blob/master/ws.html

Socket.IO Client

Socket.IO client example using vanilla JavaScript:

var l = document.getElementById('l');
var log = function (m) {
    var i = document.createElement('li');
    i.innerText = new Date().toISOString()+' '+m;
    l.appendChild(i);
}
log('opening socket.io connection');
var s = io();
s.on('connect_error', function (m) { log("error"); });
s.on('connect', function (m) { log("socket.io connection open"); });
s.on('message', function (m) { log(m); });

Source: https://github.com/rsp/node-websocket-vs-socket.io/blob/master/si.html

Network traffic

To see the difference in network traffic you can run my test. Here are the results that I got:

WebSocket Results

2 requests, 1.50 KB, 0.05 s

From those 2 requests:

  1. HTML page itself
  2. connection upgrade to WebSocket

(The connection upgrade request is visible on the developer tools with a 101 Switching Protocols response.)

Socket.IO Results

6 requests, 181.56 KB, 0.25 s

From those 6 requests:

  1. the HTML page itself
  2. Socket.IO's JavaScript (180 kilobytes)
  3. first long polling AJAX request
  4. second long polling AJAX request
  5. third long polling AJAX request
  6. connection upgrade to WebSocket

Screenshots

WebSocket results that I got on localhost:

WebSocket results - websocket-vs-socket.io module

Socket.IO results that I got on localhost:

Socket.IO results - websocket-vs-socket.io module

Test yourself

Quick start:

# Install:
npm i -g websocket-vs-socket.io
# Run the server:
websocket-vs-socket.io

Open http://localhost:3001/ in your browser, open developer tools with Shift+Ctrl+I, open the Network tab and reload the page with Ctrl+R to see the network traffic for the WebSocket version.

Open http://localhost:3002/ in your browser, open developer tools with Shift+Ctrl+I, open the Network tab and reload the page with Ctrl+R to see the network traffic for the Socket.IO version.

To uninstall:

# Uninstall:
npm rm -g websocket-vs-socket.io

Browser compatibility

As of June 2016 WebSocket works on everything except Opera Mini, including IE higher than 9.

This is the browser compatibility of WebSocket on Can I Use as of June 2016:

enter image description here

See http://caniuse.com/websockets for up-to-date info.


Its advantages are that it simplifies the usage of WebSockets as you described in #2, and probably more importantly it provides fail-overs to other protocols in the event that WebSockets are not supported on the browser or server. I would avoid using WebSockets directly unless you are very familiar with what environments they don't work and you are capable of working around those limitations.

This is a good read on both WebSockets and Socket.IO.

http://davidwalsh.name/websocket