Difference between revisions of "Socket.IO"
| (22 intermediate revisions by 4 users not shown) | |||
| Line 1: | Line 1: | ||
| − | AJAX is useful when one-way communication is satisfactory for your web application. | + | AJAX is useful when one-way communication is satisfactory for your web application. However, what happens when you need true two-way communication, such as a chat client, collaborative app, or multiplayer game? AJAX is not the right tool for that job. This is where '''Socket.IO''' comes in. |
| − | + | Socket.IO enables low-latency, bidirectional, event-based communication between the server and the client. Unlike AJAX polling, the server can send messages to the client without the client requesting them first. As you learn Socket.IO, the concept of non-blocking I/O in Node.js will become very important. | |
== Installing Socket.IO == | == Installing Socket.IO == | ||
| − | Before | + | Before installing Socket.IO, you should already have [[Node.JS]] installed and be comfortable with the project setup used in the previous section (npm init, ES Modules, etc.). |
| − | + | If you are starting a new project: | |
| + | |||
| + | <source lang="bash"> | ||
| + | $ mkdir chat | ||
| + | $ cd chat | ||
| + | $ npm init -y | ||
| + | </source> | ||
| + | |||
| + | '''Important:''' Ensure your <code>package.json</code> contains: | ||
| + | |||
| + | <source lang="json"> | ||
| + | "type": "module" | ||
| + | </source> | ||
| + | |||
| + | This enables modern ES Module syntax (<code>import</code>). | ||
| + | |||
| + | Now install Socket.IO: | ||
<source lang="bash"> | <source lang="bash"> | ||
| Line 13: | Line 29: | ||
</source> | </source> | ||
| − | + | Socket.IO is installed locally inside <code>node_modules</code> and recorded automatically in <code>package.json</code>. | |
== Messaging == | == Messaging == | ||
| − | Socket.IO | + | Socket.IO uses an event-based model. Clients and servers send named events to each other. |
| + | |||
| + | Example: | ||
<source lang="javascript"> | <source lang="javascript"> | ||
| − | // | + | // Sender (client or server) |
| − | socket.emit("info", { | + | socket.emit("info", { hello: "world" }); |
| − | |||
| − | }); | ||
| − | // | + | // Receiver (client or server) |
| − | socket.on("info", | + | socket.on("info", (data) => { |
| − | + | console.log(data.hello); | |
}); | }); | ||
</source> | </source> | ||
| − | + | When <code>socket.emit(name, data)</code> is called, any listener registered with <code>socket.on(name, ...)</code> will execute and receive the data. | |
| + | |||
| + | Either side (client or server) can emit or receive events. | ||
== A First Socket.IO Application: Chat Server and Client == | == A First Socket.IO Application: Chat Server and Client == | ||
| − | Building a chat | + | Building a simple chat application demonstrates the fundamentals of Socket.IO and real-time communication. Understanding this example will make later group features (rooms, private messaging, etc.) much easier. |
=== The Chat Server === | === The Chat Server === | ||
| − | + | Create a file named <code>chat-server.js</code>: | |
<source lang="javascript"> | <source lang="javascript"> | ||
| − | + | import { createServer } from "node:http"; | |
| − | + | import { readFile } from "node:fs/promises"; | |
| − | + | import { Server } from "socket.io"; | |
| − | |||
| − | // | + | const port = 3456; |
| − | + | const file = "client.html"; | |
| − | + | ||
| − | + | // Minimal HTTP server that serves client.html | |
| − | + | const httpServer = createServer(async (req, res) => { | |
| − | + | try { | |
| − | + | const data = await readFile(file); | |
| − | + | res.writeHead(200, { "Content-Type": "text/html" }); | |
| − | + | res.end(data); | |
| + | } catch { | ||
| + | res.writeHead(500, { "Content-Type": "text/plain" }); | ||
| + | res.end("Could not load client.html"); | ||
| + | } | ||
}); | }); | ||
| − | |||
| − | // | + | // Attach Socket.IO to the HTTP server |
| − | io | + | const io = new Server(httpServer); |
| − | + | ||
| − | + | io.on("connection", (socket) => { | |
| − | + | console.log("New connection:", socket.id); | |
| − | + | ||
| − | + | socket.on("message_to_server", (data) => { | |
| − | + | console.log("message:", data.message); | |
| + | |||
| + | // Broadcast message to all connected clients | ||
| + | io.emit("message_to_client", { message: data.message }); | ||
| + | }); | ||
| + | }); | ||
| + | |||
| + | httpServer.listen(port, () => { | ||
| + | console.log(`Server running at http://localhost:${port}/`); | ||
}); | }); | ||
</source> | </source> | ||
| − | + | What this server does: | |
| + | |||
| + | * Serves <code>client.html</code> | ||
| + | * Accepts Socket.IO connections | ||
| + | * Listens for <code>message_to_server</code> events | ||
| + | * Broadcasts messages to all clients | ||
=== The Chat Client === | === The Chat Client === | ||
| − | + | Create <code>client.html</code>: | |
<source lang="html4strict"> | <source lang="html4strict"> | ||
| Line 80: | Line 113: | ||
<html> | <html> | ||
<head> | <head> | ||
| − | <title>Chat | + | <meta charset="utf-8"> |
| + | <title>Socket.IO Chat</title> | ||
| + | </head> | ||
| + | |||
| + | <body> | ||
| + | |||
| + | <input type="text" id="message_input"> | ||
| + | <button id="send_btn">Send</button> | ||
| + | <div id="chatlog"></div> | ||
| − | |||
<script src="/socket.io/socket.io.js"></script> | <script src="/socket.io/socket.io.js"></script> | ||
| − | |||
| − | |||
| − | |||
<script> | <script> | ||
| − | + | const socket = io(); | |
| − | + | socket.on("message_to_client", (data) => { | |
| − | socket.on(" | + | const chatlog = document.getElementById("chatlog"); |
| − | + | chatlog.appendChild(document.createElement("hr")); | |
| − | + | chatlog.appendChild(document.createTextNode(data.message)); | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
}); | }); | ||
| + | |||
| + | function sendMessage() { | ||
| + | const input = document.getElementById("message_input"); | ||
| + | const msg = input.value; | ||
| + | socket.emit("message_to_server", { message: msg }); | ||
| + | input.value = ""; | ||
| + | } | ||
| + | |||
| + | document.getElementById("send_btn").addEventListener("click", sendMessage); | ||
</script> | </script> | ||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
</body> | </body> | ||
</html> | </html> | ||
</source> | </source> | ||
| − | + | This example sends a JavaScript object as event data, but any datatype may be used. | |
| + | |||
| + | === Running the Chat Server === | ||
| + | |||
| + | Start the server: | ||
| + | |||
| + | <source lang="bash"> | ||
| + | $ node chat-server.js | ||
| + | </source> | ||
| + | |||
| + | Open: | ||
| + | |||
| + | http://localhost:3456/ | ||
| + | |||
| + | Open the page in two browser windows. Messages typed in one window appear in the other — a simple real-time chat system. | ||
| + | |||
| + | If running on EC2, ensure port 3456 is open. | ||
| + | |||
| + | == Broadcasting Behavior == | ||
| + | |||
| + | Socket.IO supports several broadcast patterns: | ||
| + | |||
| + | * <code>io.emit(...)</code> → send to all clients | ||
| + | * <code>socket.broadcast.emit(...)</code> → send to all except sender | ||
| + | * <code>io.to(room).emit(...)</code> → send to a specific room | ||
| + | |||
| + | == Rooms (Concept) == | ||
| + | |||
| + | Rooms allow grouping sockets so messages only go to certain users (e.g., chat rooms, game sessions). | ||
| + | |||
| + | Example: | ||
| + | |||
| + | <source lang="javascript"> | ||
| + | io.on("connection", (socket) => { | ||
| + | |||
| + | socket.on("join_room", (data) => { | ||
| + | socket.join(data.room); | ||
| + | }); | ||
| − | + | socket.on("room_message", (data) => { | |
| + | io.to(data.room).emit("message_to_client", { | ||
| + | message: data.message | ||
| + | }); | ||
| + | }); | ||
| − | + | }); | |
| + | </source> | ||
| − | + | Rooms are managed on the server and are invisible to clients. | |
== Resources == | == Resources == | ||
| − | + | * https://socket.io/docs/v4/ | |
| + | * Rooms documentation: https://socket.io/docs/v4/rooms/ | ||
| − | [[Category:Module | + | [[Category:Module 5]] |
Latest revision as of 13:31, 1 March 2026
AJAX is useful when one-way communication is satisfactory for your web application. However, what happens when you need true two-way communication, such as a chat client, collaborative app, or multiplayer game? AJAX is not the right tool for that job. This is where Socket.IO comes in.
Socket.IO enables low-latency, bidirectional, event-based communication between the server and the client. Unlike AJAX polling, the server can send messages to the client without the client requesting them first. As you learn Socket.IO, the concept of non-blocking I/O in Node.js will become very important.
Contents
Installing Socket.IO
Before installing Socket.IO, you should already have Node.JS installed and be comfortable with the project setup used in the previous section (npm init, ES Modules, etc.).
If you are starting a new project:
$ mkdir chat
$ cd chat
$ npm init -y
Important: Ensure your package.json contains:
"type": "module"
This enables modern ES Module syntax (import).
Now install Socket.IO:
$ npm install socket.io
Socket.IO is installed locally inside node_modules and recorded automatically in package.json.
Messaging
Socket.IO uses an event-based model. Clients and servers send named events to each other.
Example:
// Sender (client or server)
socket.emit("info", { hello: "world" });
// Receiver (client or server)
socket.on("info", (data) => {
console.log(data.hello);
});
When socket.emit(name, data) is called, any listener registered with socket.on(name, ...) will execute and receive the data.
Either side (client or server) can emit or receive events.
A First Socket.IO Application: Chat Server and Client
Building a simple chat application demonstrates the fundamentals of Socket.IO and real-time communication. Understanding this example will make later group features (rooms, private messaging, etc.) much easier.
The Chat Server
Create a file named chat-server.js:
import { createServer } from "node:http";
import { readFile } from "node:fs/promises";
import { Server } from "socket.io";
const port = 3456;
const file = "client.html";
// Minimal HTTP server that serves client.html
const httpServer = createServer(async (req, res) => {
try {
const data = await readFile(file);
res.writeHead(200, { "Content-Type": "text/html" });
res.end(data);
} catch {
res.writeHead(500, { "Content-Type": "text/plain" });
res.end("Could not load client.html");
}
});
// Attach Socket.IO to the HTTP server
const io = new Server(httpServer);
io.on("connection", (socket) => {
console.log("New connection:", socket.id);
socket.on("message_to_server", (data) => {
console.log("message:", data.message);
// Broadcast message to all connected clients
io.emit("message_to_client", { message: data.message });
});
});
httpServer.listen(port, () => {
console.log(`Server running at http://localhost:${port}/`);
});
What this server does:
- Serves
client.html - Accepts Socket.IO connections
- Listens for
message_to_serverevents - Broadcasts messages to all clients
The Chat Client
Create client.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Socket.IO Chat</title>
</head>
<body>
<input type="text" id="message_input">
<button id="send_btn">Send</button>
<div id="chatlog"></div>
<script src="/socket.io/socket.io.js"></script>
<script>
const socket = io();
socket.on("message_to_client", (data) => {
const chatlog = document.getElementById("chatlog");
chatlog.appendChild(document.createElement("hr"));
chatlog.appendChild(document.createTextNode(data.message));
});
function sendMessage() {
const input = document.getElementById("message_input");
const msg = input.value;
socket.emit("message_to_server", { message: msg });
input.value = "";
}
document.getElementById("send_btn").addEventListener("click", sendMessage);
</script>
</body>
</html>
This example sends a JavaScript object as event data, but any datatype may be used.
Running the Chat Server
Start the server:
$ node chat-server.js
Open:
Open the page in two browser windows. Messages typed in one window appear in the other — a simple real-time chat system.
If running on EC2, ensure port 3456 is open.
Broadcasting Behavior
Socket.IO supports several broadcast patterns:
io.emit(...)→ send to all clientssocket.broadcast.emit(...)→ send to all except senderio.to(room).emit(...)→ send to a specific room
Rooms (Concept)
Rooms allow grouping sockets so messages only go to certain users (e.g., chat rooms, game sessions).
Example:
io.on("connection", (socket) => {
socket.on("join_room", (data) => {
socket.join(data.room);
});
socket.on("room_message", (data) => {
io.to(data.room).emit("message_to_client", {
message: data.message
});
});
});
Rooms are managed on the server and are invisible to clients.
Resources
- https://socket.io/docs/v4/
- Rooms documentation: https://socket.io/docs/v4/rooms/