The web has come a long way to allow two-way communication between a client and server via HTTP. HTTP never sends data to a client without having been queried first. This is ideal for a wide range of online applications. It enables loose coupling between clients and servers while avoiding maintaining a persistent connection. The WebSocket establishes two-way communication between a client and server over a single TCP connection in real-time.
For real-time applications, the request-response pattern that HTTP provides has disadvantages. The client is not informed when some server state changes. The client has to request data at regular intervals. This is not ideal since the data will not be complete in real-time, and shorter polling intervals will result in more network traffic.
WebSockets is a web technology that allows two-way communication between the browser and server. Today, most modern browsers support it WebSocket. Socket.IO is a library that provides a high-level WebSocket API.
We’ll be building a chat application using Socket.IO, React for the front-end, and Node for the back-end.
The WebSocket protocol’s only aims are:
The real-time communication between a WebSocket client and server happens over a single TCP socket using either WS (port 80) or WSS (port 443) protocol.
Historically, multiple methods were used to develop web apps that required real-time data. Achieve real-time capabilities, but none of them were as efficient as WebSockets. However, WebSockets was more efficient than others like HTTP polling, HTTP streaming, Comet, and SSE.
The first attempt to address the problem was to poll the server at set intervals. Long polling had several flaws, including header overhead, latency, timeouts, caching, and so on.
The request is never terminated, and the connection remains open and sends fresh updates until there is a change.
Websockets and SSE are nearly identical in their handling of incoming events. SSE is a one-way connection; you can’t send event information from a client to a server. The server pushes data to the client.
It is similar to SSE, but it has a full-duplex channel with real-time communications. That means it also takes messages back from the client to the server.
Let’s create a simple chat app using Socket.io, Express, and React.
In a command prompt or terminal window, execute the following.
npx express-generator --no-view chat-server
then
npm install
then
npm install -E socket.io@4.4.0 uuid@8.3.2 cors@2.8.5
Now, create a new file chat.js in the project folder using an editor of your choice. Replace the following text in your file with this code.
const uuidv4 = require('uuid').v4 const messages = new Set() const users = new Map() const defaultUser = { id: 'nisar', name: 'Anonymous' } const messageExpirationTimeMS = 5 * 60 * 1000 class Connection { constructor(io, socket) { this.socket = socket this.io = io socket.on('getMessages', () => this.getMessages()) socket.on('message', value => this.message(value)) socket.on('disconnect', () => this.disconnect()) socket.on('connect_error', err => { console.log(`connect_error due to ${err.message}`) }) } sendMessage(message) { this.io.sockets.emit('message', message) } getMessages() { messages.forEach(message => this.sendMessage(message)) } message(value) { const message = { id: uuidv4(), user: users.get(this.socket) || defaultUser, value, time: Date.now() } messages.add(message) this.sendMessage(message) setTimeout(() => { messages.delete(message) this.io.sockets.emit('deleteMessage', message.id) }, messageExpirationTimeMS) } disconnect() { users.delete(this.socket) } } function chat(io) { io.on('connection', socket => { new Connection(io, socket) }) } module.exports = chat
Let’s walk through code above in chart.js.
The evolution of the web has necessitated the development of tools and protocols that can accommodate the ever-growing need for real-time data exchange. WebSockets emerges as a clear victor in this context, offering efficient two-way communication over a single, persistent connection. It effectively mitigates the limitations faced by earlier approaches like HTTP polling, HTTP streaming, and SSE.
In the chat application example using Socket.io, Express, and React, we’ve demonstrated the ease with which we can set up real-time communication for a practical use-case. The primary functions are simple to grasp, with messages being added to a set, users tracked in a map, and the seamless broadcasting of messages to all connected clients.
Furthermore, the code also ensures that messages are not held indefinitely, addressing potential memory management concerns. With tools and libraries like Socket.io at our disposal, building real-time applications has become more straightforward than ever. As developers, it’s vital to understand and embrace these technologies to craft user experiences that are immediate, interactive, and immersive.
Quick Links
Legal Stuff