Intro

I’ve not had the opportunity to work with websockets before but I’ve always heard about them. Mainly when used for fast real-time updates across web systems. Examples include chat apps, multiplayer games, live comment sections, etc.

What do they Do?

Most web architecture revolves around client-server architecture communicating via http but this is slow, as requests have to sent, responses awaited.

So Web-sockets remove the need for constantly sending requests and responses back and forth, by creating a persistent connection between client and server, and messages are sent along this connection anytime without the need for request-response.

Form and Structure

Every websocket connection starts as a normal HTTP request to establish it, this happens by the client asking if the server can promote this connection to a websocket. Then protocols are switched and the connection stays open.

Unlike HTTP, Websockets don’t work routes, they work based on events that happen on the socket connection on a specific port.

Client Side (JS example)

If we have a JS module that needs to create a websocket connection, it’ll look something like this:

const wsock = newWebSocket("ws://localhost:3000");

// notice the ws instead of http protocol.

To observe if the connection is ready and established, we need to listen to the open event fired by the server.

const wsock = new WebSocket("ws://localhost:3000");
 
// What to do when the connection is opened
wsock.onopen = () => {
	// do stuff
	console.log("We groovy");
}

Sending data

Once the connection is established, it’s as simple as using the send method on the socket object.

const wsock = newWebSocket("ws://localhost:3000");
 
wsock.send("The Grid. A digital frontier...");

There’s no request & response, the message just goes through and gets handled by the server.

Handling Messages

When a server sends data to the client, the browser will trigger an event.
By writing listeners to these events, we can handle the incoming data from the server

const wsock = newWebSocket("ws://localhost:3000");
 
wsock.onmessage = (event) => {
	// do stuff with `event`
	console.log("got a msg from the Grid: ", event.data);
};
 
wsock.onerror = (err) => {
	// do stuff with `err`
	console.log("got an error: ", error);
};

//this isn't perfect way to structure this, just example for learning

Closing Connection

Websocket connection close for various reasons.

  • User leaving page
  • Server shut down
  • Timeouts
    We must handle this event as well.
const wsock = newWebSocket("ws://localhost:3000");
 
wsock.onlcose = () => {
	console.log("End of Line!");
};

Server side

The server’s main responsibility is to keep the connection open and handle the incoming messages/data.

In Node.js, the most popular library is ws and it’s pretty solid and transparent about how it works.

Creating WS Server

const Websocket = require("ws");
 
// Creating a server listening for ws connections on this port
const wsServer = new Websocket.Server({port: 3000})

Reacting to connection

const Websocket = require("ws");
 
// Creating a server listening for ws connections on this port
const wsServer = new Websocket.Server({port: 3000})
 
wsServer.on("connection", (socket) => {
	// do somethiong
	console.log("got connection request from Flyn, on socket ", socket);
	
	socket.on("message", (msg)=>{
		// do somthing with the message which comes in as raw data not a string
		console.log("Flyn says: '", msg.toString(), "'");
		socket.send("Received, initiating...");
	});
})

References