{ Real Time Applications with Socket.io. }

Objectives:

By the end of this chapter, you should be able to:

  • Define what a websocket is
  • Compare and contrast the HTTP and WS protocols
  • Build an express application using socket.io

Socket.io

One of the most popular libraries when working with Node is Socket.io, which is a library for handling websocket connections and communication between multiple clients and servers. There is a built-in module for Node for websockets, but the Socket.io library abstracts quite a bit of detail for us, making it setup much more straightforward. But first, let's try to understand what a websocket is.

With the HTTP protocol, a client and server communicate via the request-response cycle. The client initiates a request, the server issues a response, and the cycle is complete. When that interaction is over, the connection between client and server is complete (though the connection can be kept alive via HTTP headers).

With WebSockets, clients and servers connect through a process called a "handshake" and then keep the communication open, which allows for bidirectional communications: the client can push data to the server, but the server can also push data to the client without first waiting for a request to come in! This allows for applications that feel as though they are updating and responding to user input in real time. Chat rooms and multiplayer games are both examples of applications that can benefit from using websockets.

The ws or websocket protocol is an upgrade from another strategy known as "longpolling," which involves making frequent AJAX calls to see if the server has any new information and then updating the client accordingly.

You can read more about Socket.io here. Let's get started with a simple application.

mkdir learn_socket_io && cd learn_socket_io
touch app.js
npm init -y
npm install --save express socket.io
mkdir views
touch views/index.html

Here is what our app.js looks like:

var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);

app.get('/', function(req, res, next){
  res.sendFile(__dirname + '/views/index.html');
});

io.on('connection', function(socket){
  console.log("connection!");

  io.sockets.emit('from server', 'HELLO!');

  socket.on('from client', function(data){
    console.log(data);
  });
});

http.listen(3000, function(){
  console.log('listening on localhost:3000');
});

The most important part of the code is what's happening inside of the io.on. Fundamentally, websocket connections in socket.io are responsible for two things: emitting events using the emit method, and listening for emitted events using the on method. These two methods are the foundation of communciation in socket.io.

Here, we're saying that whenever a client connects to a server, we should create a websocket connection, and then that connection should emit an event called "from server" along with a message of "HELLO!".

We're also setting listeners on the server for events from clients. When a client emits an event called "from client", the server should take the data from that event and log it to the terminal.

In order to get our application working, we next need to set up some code on the client to create the websocket connection, emit events, and listen for emitted events. Here's our index.html:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>First Socket.io application</title>
</head>
<body>
  <script src="/socket.io/socket.io.js"></script>
  <script>
    var socket = io();

    socket.on('from server', function (data) {
      console.log(data);
      socket.emit('from client', 'WORLD!');
    });
  </script>
</body>
</html>

Let's step through the sequence of events when this page loads:

  1. The client creates a websocket connection with the server (var socket = io()).
  2. Whenever a connection is created, the server receives a 'conncection' event. In our application, this causes the server to send to all connected websockets a 'from server' event, with a message of 'HELLO!'.
  3. The client is set up to receive 'from server' events. When it receives such a request, it console lots the data, then emits its own event, called 'from client', with data of 'WORLD!'.
  4. One the server receives a 'from client' event, it logs the corresponding data to the terminal.

One thing to note is that when a client connects, the 'from server' event gets emitted to all websocket connections (we emit on io.sockets, not socket). You can verify that all clients receive the event by going to localhost:3000 on two separate tabs. The first tab should have 'HELLO!' logged twice: once when it connected to the server, and once when the other tab connected!

For another example using Socket.io, check out the chat room tutorial in their documentation.

Different kinds of messages and rooms

When using Socket.io, there are different types of messages you may want to send to different users. For managing chat rooms, socket.io has the idea of a room which has its own name and each socket has its own id to ensure private messages can work.

Here are the helpful methods for sending certain types of messages to certain users:

io.emit('name of event'); or io.sockets.emit('name of event'); - sends to everyone in every room, including the sender

io.to('name of room').emit('name of event'); - sends to everyone including the sender, in a room (the first parameter to to)

socket.broadcast.to('name of room').emit('name of event'); - sends to everyone except the sender in a room (the first parameter to to)

socket.emit('name of event') - sends to the sender and no one else

socket.broadcast.to(someOtherSocket.id).emit(); - Send to specific socket only (used for private chat)

Example Application

You can see a small chat example with socket.io here.

When you're ready, move on to Sending Email with Nodemailer

Continue