Websocket Bi-directional Broadcast Demo

Node Setup

Install node module to generate UUID to keep track of clients that connect to the WebSocket chat server.

npm install node-uuid

This gives an error:

npm uninstall --save node-uuid
npm WARN deprecated node-uuid@1.4.7: use uuid module instead

The fix is:

npm uninstall --save node-uuid
npm install --save uuid

WebSocket Server

The WebSocket server code in server.js looks like this:

var WebSocket = require('ws');
var WebSocketServer = WebSocket.Server,
    wss = new WebSocketServer({port: 8080});
var uuid = require('node-uuid');

var clients = [];

wss.on('connection', function(ws) {
  var client_uuid = uuid.v4();
  clients.push({"id": client_uuid, "ws": ws});
  console.log('client [%s] connected', client_uuid);
  ws.on('message', function(message) {
    for(var i=0; i<clients.length; i++) {
        var clientSocket = clients[i].ws;
        if(clientSocket.readyState === WebSocket.OPEN) {
            console.log('client [%s]: %s', clients[i].id, message);
            clientSocket.send(JSON.stringify({
                "id": client_uuid,
                "message": message
            }));
        }
    }
  });

  ws.on('close', function() {
    for(var i=0; i<clients.length; i++) {
        if(clients[i].id == client_uuid) {
            console.log('client [%s] disconnected', client_uuid);
            clients.splice(i, 1);
        }
    }
  });
});

We save the uuid.v4 value to the client_uuid variable. We can now identify messages sent and any close event. We store a JSON with UUID and the WebSocket object in the clients array. The server receives the message from the client and iterates over all the connected clients collection to send the messages to them. The clients connected to the server will receive the JSON string that is shown to the end user. The server listens for a close event, when it receives it for a given client, it iterates through the collection and removes the client.

WebSocket Client

The websocket client is shown below:

<!DOCTYPE html>
<html lang="en">
<head>
<title>WebSocket Chat Demo</title>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<script>
  var ws = new WebSocket("ws://localhost:8080");
  ws.onopen = function(e) {
    console.log('Connection to server opened');
  }
  function appendLog(message) {
    var messages =  document.getElementById('messages');
    var messageElem = document.createElement("li");

    messageElem.innerHTML = "<h2>" + message + "</h2>";
    messages.appendChild(messageElem);
  }
  ws.onmessage = function(e) {
     var data = JSON.parse(e.data);
     appendLog(data.message);
     console.log("ID: [%s] = %s", data.id, data.message);
  }
  ws.onclose = function(e) {
    appendLog("Connection closed");
    console.log("Connection closed");
  }
  function sendMessage() {
    if(ws.readyState === WebSocket.OPEN) {
      ws.send($('#message').val());
    }
    $('#message').val('');
    $('#message').focus();
  }
  function disconnect() {
    ws.close();
  }
</script> 
</head>
<body lang="en">
  <div class="container">
    <ul id="messages">
    </ul>
    <hr />
    <form role="form" id="chat_form" onsubmit="sendMessage(); return false;">
       <div class="form-group">
          <input class="form-control" type="text" name="message" id="message" placeholder="Type your message here" value="" autofocus/>
        </div>
        <button type="button" id="send" onclick="sendMessage();">Send Message</button>
    </form>
  </div>
</body>
</html>

The client receives a message in JSON format from the server. We use JavaScript built-in parsing function to extract the message field. The message is appended to an unordered list using the appendChild method. Now you can open the index.html in two different tabs or browsers and simulate a chat session. In this article, you learned how broadcasting to multiple clients works in websockets. We created a WebSocket server that can broadcast the messages received from a client to all the connected clients. This completes the series of articles on WebSocket focused on concepts required to grasp ActionCable.


Related Articles


Create your own user feedback survey