In the digital realm, timely and seamless communication is pivotal for an enhanced user experience. One technology that stands out in facilitating real-time communication is WebSockets. Unlike traditional HTTP, where communication is initiated only by the client, WebSockets offer a two-way communication channel between the client and server, making real-time updates a breeze.
Let’s embark on a simple journey to understand WebSockets and how they are implemented in JavaScript, along with practical examples. Additionally, we'll discern scenarios where they prove to be a better choice.
Understanding WebSockets
WebSockets provide a unique channel of communication where both the client and server can send data independently at any time. This is a significant upgrade from the conventional request-response model where the communication is always initiated by the client.
Implementing WebSockets in JavaScript
Let’s create a simple WebSocket connection in JavaScript. Firstly, ensure your server supports WebSocket connections.
// Creating a new WebSocket instance
const socket = new WebSocket('ws://your-websocket-server.com');
// Connection opened
socket.addEventListener('open', (event) => {
socket.send('Hello Server!');
});
// Listen for messages
socket.addEventListener('message', (event) => {
console.log('Message from server:', event.data);
});
// Connection closed
socket.addEventListener('close', (event) => {
console.log('Server connection closed:', event.data);
});
In this snippet:
- We create a new
WebSocket
instance, passing the WebSocket server URL. - We attach an event listener for the
open
event, which triggers when the connection is established, sending a greeting to the server. - We listen for any messages from the server with the
message
event. - Finally, we have a listener for the
close
event, which triggers when the connection is closed.
When to Use WebSockets?
WebSockets are particularly useful when you have a need for real-time updates. Here are some use cases:
- Chat Applications: Real-time message delivery is crucial for chat applications, making WebSockets a perfect fit.
- Live Updates: Whether it's a stock market application or a live score update of a game, WebSockets provide the real-time data transmission required.
- Online Gaming: Multiplayer online games benefit from the low latency and real-time updates provided by WebSockets.
- Collaboration Tools: Tools like document editors or project boards, where multiple users collaborate in real-time, also benefit significantly from WebSockets.
WebSockets bridge the gap between client and server, making real-time communication not just a possibility, but a robust, efficient reality. As you delve into projects that require a seamless flow of data, harnessing the power of WebSockets in JavaScript will undoubtedly prove to be a game-changer.
Websocket server with NodeJs and express
Creating a WebSocket server alongside an Express application requires the ws
library, which is a popular WebSocket library for Node.js. Below is a basic example of how you can set up a WebSocket server using Node.js and Express.
- Firstly, you'll need to install
express
andws
using npm:
npm install express ws
- Now create a file named
server.js
and paste the following code into it:
const express = require('express');
const http = require('http');
const WebSocket = require('ws');
const app = express();
// Initialize a simple http server
const server = http.createServer(app);
// Initialize the WebSocket server instance
const wss = new WebSocket.Server({ server });
wss.on('connection', (ws) => {
// Connection is up, let's add a simple event
ws.on('message', (message) => {
console.log('Received:', message);
// Broadcast the message to all connected clients
wss.clients.forEach(client => {
if (client !== ws && client.readyState === WebSocket.OPEN) {
client.send(`Broadcast: ${message}`);
}
});
});
// Send a welcome message to the new connection
ws.send('Welcome to the WebSocket server!');
});
// Start the server on port 8080
server.listen(8080, () => {
console.log('Server is listening on port 8080');
});
In this code:
- We create an Express app and an HTTP server.
- We initialize a new WebSocket server instance, binding it to the HTTP server.
- We listen for new WebSocket connections on the
connection
event. For each new connection, we:- Set up a listener for
message
events, logging the received message to the console and broadcasting it to all other connected clients. - Send a welcome message to the newly connected client.
- Set up a listener for
Now, to start your server, run the following command in the terminal:
node server.js
Your WebSocket server will now be running on http://localhost:8080
. You can connect to it using the WebSocket client code from the previous section of the article, just replace 'ws://your-websocket-server.com'
with 'ws://localhost:8080'
.
Certainly! You can create a WebSocket server using just the ws
library and Node.js's built-in http
module. Below is how you could go about this:
- As before, ensure you have the
ws
library installed via npm:
npm install ws
- Create a file named
server.js
and paste the following code into it:
const http = require('http');
const WebSocket = require('ws');
// Create an HTTP server
const server = http.createServer((req, res) => {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello World\n');
});
// Initialize the WebSocket server instance
const wss = new WebSocket.Server({ server });
wss.on('connection', (ws) => {
// Connection is established
ws.on('message', (message) => {
// Log the received message
console.log('Received:', message);
// Broadcast the message to all connected clients
wss.clients.forEach(client => {
if (client !== ws && client.readyState === WebSocket.OPEN) {
client.send(`Broadcast: ${message}`);
}
});
});
// Send a welcome message to the new connection
ws.send('Welcome to the WebSocket server!');
});
// Start the server on port 8080
server.listen(8080, () => {
console.log('Server is listening on port 8080');
});
In this code:
- We create an HTTP server using Node.js's built-in
http
module. - We initialize a new WebSocket server instance, binding it to the HTTP server.
- We listen for new WebSocket connections on the
connection
event. For each new connection, we:- Set up a listener for
message
events, logging the received message to the console and broadcasting it to all other connected clients. - Send a welcome message to the newly connected client.
- Set up a listener for
To start your server, run the following command in the terminal:
node server.js
Your WebSocket server will now be running on http://localhost:8080
. You can connect to it using the WebSocket client code from your earlier request, just replace 'ws://your-websocket-server.com'
with 'ws://localhost:8080'
.
Creating Chat Room
First let's create a client's UI (a html page)
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>WebSocket client</title>
</head>
<body>
<button id="sendmessagebutton">Broadcast Message</button>
<button id="sendtoserver">Send Message to server</button>
<p id="logging">Logging:</p>
<script src="client.js"></script>
</body>
</html>
- The "Broadcast Message" button is for sending a message for broadcasting
- The "Send message to server" is for sending message only to server
- The paragraph is for logging things on the client
Now let's change a little bit the client.js
// Creating a new WebSocket instance
const socket = new WebSocket('ws://localhost:8080');
// Connection opened
socket.addEventListener('open', (event) => {
var sayhi = {
"type": "SENDTOSERVER",
"payload": {
"message": "Hello server, How are you?"
}
}
socket.send(JSON.stringify(sayhi));
document.getElementById("logging").innerText += "\n" + "You sent this mesage to the server: " + sayhi.payload.message
document.getElementById("sendmessagebutton").addEventListener("click", () => {
var newmessage = {
"type": "BROADCAST",
"payload": {
"author": "A USER",
"message": "Hi everyone!"
}
}
socket.send(JSON.stringify(newmessage))
document.getElementById("logging").innerText += "\n" + "You sent this mesage for broadcasting to the server: " + newmessage.payload.message
})
document.getElementById("sendtoserver").addEventListener("click", () => {
var newmessage = {
"type": "SENDTOSERVER",
"payload": {
"author": "A USER",
"message": "This message is for server only"
}
}
socket.send(JSON.stringify(newmessage))
})
});
// Listen for messages
socket.addEventListener('message', (event) => {
try {
var message = JSON.parse(event.data);
if (message.type === 'BROADCAST') {
document.getElementById("logging").innerText += "\n" + "A client broadcasted: " + message.payload.message
} else {
document.getElementById("logging").innerText += "\n" + "You received this message: " + message.payload.message
}
} catch (e) {
console.log('Wrong format');
return;
}
});
// Connection closed
socket.addEventListener('close', (event) => {
console.log('Server connection closed:', event.data);
});
We will change the server so it can differentiate the messages that are for broadcasting and for server only.
const express = require('express');
const http = require('http');
const WebSocket = require('ws');
const path = require('path');
const app = express();
app.set("public", path.join(__dirname, "/"));
app.use(express.static(app.get("public")));
// Initialize a simple http server
const server = http.createServer(app);
// Initialize the WebSocket server instance
const wss = new WebSocket.Server({ server });
wss.on('connection', (ws) => {
// Connection is up, let's add a simple event
ws.on('message', (data) => {
console.log('Received:', data.toString());
let message;
try {
message = JSON.parse(data);
} catch (e) {
console.log('Wrong format');
return;
}
if (message.type === 'BROADCAST') {
// Broadcast the message to all connected clients
wss.clients.forEach(client => {
if (client !== ws && client.readyState === WebSocket.OPEN) {
var newmessage = {
"type": "BROADCAST",
"payload": {
"author": "Server",
"message": message.payload.message
}
}
client.send(JSON.stringify(newmessage));
}
});
}
if (message.type === 'SENDTOSERVER') {
var respond = {
"type": "SERVER_MESSAGE",
"payload": {
"author": "Server",
"message": "I received your message:<<" + message.payload.message + ">>"
}
}
ws.send(JSON.stringify(respond));
}
});
// Send a welcome message to the new connection
var message = { type: "SERVER_MESSAGE", payload: { message: "Hello client You just connected!" } }
ws.send(JSON.stringify(message));
});
// sendFile will go here
app.get('/', function (req, res) {
res.sendFile(path.join(__dirname, '/index.html'));
});
// Start the server on port 8080
server.listen(8080, () => {
console.log('Server is listening on port 8080');
});
Let's test things:
run node server.js
Then visit http://localhost:8080/
You should see this:
If you open a second tab you will connect a second client:
Then you can broadcast messages(press "Broadcast Message") The server will receive the message and will broadcast it to the clients (except sender)
Also, you can send messages only to the server and get a response
That's for now!
You can find the code of this article here : GitHub Repository
Thank you for your time and for reading!