Difference between revisions of "Socket.IO"

From CSE330 Wiki
Jump to navigationJump to search
m
 
(29 intermediate revisions by 4 users not shown)
Line 1: Line 1:
 +
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 ==
 +
 +
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">
 +
$ npm install socket.io
 +
</source>
 +
 +
Socket.IO is installed locally inside <code>node_modules</code> and recorded automatically in <code>package.json</code>.
 +
 +
== Messaging ==
 +
 +
Socket.IO uses an event-based model. Clients and servers send named events to each other.
 +
 +
Example:
 +
 +
<source lang="javascript">
 +
// Sender (client or server)
 +
socket.emit("info", { hello: "world" });
 +
 +
// Receiver (client or server)
 +
socket.on("info", (data) => {
 +
  console.log(data.hello);
 +
});
 +
</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 client is surprising simple using Socket.IO and Node.JS. We can do it in fewer than 5 minutes!
+
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 ===
  
−
You can make a file called chat.js with the following code:
+
Create a file named <code>chat-server.js</code>:
  
 
<source lang="javascript">
 
<source lang="javascript">
−
// Require the packages we will use:
+
import { createServer } from "node:http";
−
var http = require("http"),
+
import { readFile } from "node:fs/promises";
−
io = require("socket.io"),
+
import { Server } from "socket.io";
−
fs = require("fs");
+
 
 +
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);
  
−
// Listen for HTTP connections:
+
    // Broadcast message to all connected clients
−
var app = http.createServer(function(req, resp){
+
    io.emit("message_to_client", { message: data.message });
−
// This callback runs when a new connection is made to our HTTP server.
+
  });
−
fs.readFile("chat.html", function(err, data){
 
−
// This callback runs when the chat.html file has been read from the filesystem.
 
−
if(err) return resp.writeHead(500);
 
−
resp.writeHead(200);
 
−
resp.end(data);
 
−
});
 
 
});
 
});
−
app.listen(3456);
 
  
−
// Do the Socket.IO magic:
+
httpServer.listen(port, () => {
−
io.listen(app).sockets.on("connection", function(socket){
+
  console.log(`Server running at http://localhost:${port}/`);
−
// This callback runs when a new Socket.IO connection is established.
 
−
socket.on("message", function(content){
 
−
// This callback runs when the client sends us a "message" event
 
−
console.log("message: "+content); // log it to the Node.JS output
 
−
socket.broadcast.emit("someonesaid", content); // broadcast the message to other users
 
−
});
 
 
});
 
});
 
</source>
 
</source>
  
−
The above code makes a simple HTTP server that responds to all connections with the contents of the file "chat.html", which we will make in the next step.  We tell Socket.IO to listen for "message" events, and when it hears one, it should emit a new event called "someone said" back to the connected clients.
+
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 ===
  
−
Here is a front-end client that could work with our server, in `chat.html`:
+
Create <code>client.html</code>:
  
 
<source lang="html4strict">
 
<source lang="html4strict">
Line 46: Line 113:
 
<html>
 
<html>
 
<head>
 
<head>
−
<title>Chat Client</title>
+
<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>
  
−
<!-- Include the Socket.IO and Ext libraries -->
 
 
<script src="/socket.io/socket.io.js"></script>
 
<script src="/socket.io/socket.io.js"></script>
−
<script src="//cdn.sencha.io/ext-4.1.1-gpl/ext-all-dev.js"></script>
 
−
 
−
<!-- Write our custom code -->
 
 
<script>
 
<script>
−
Ext.DomHelper.useDom = true; // prevent XSS
+
const socket = io();
  
−
var socket = io.connect("http://localhost");
+
socket.on("message_to_client", (data) => {
−
socket.on("someonesaid", function(content){
+
  const chatlog = document.getElementById("chatlog");
−
// This callback runs when the server sends us a "someonesaid" event
+
  chatlog.appendChild(document.createElement("hr"));
−
Ext.fly("messages").createChild({
+
  chatlog.appendChild(document.createTextNode(data.message));
−
tag: "li",
 
−
children: [content]
 
−
});
 
−
});
 
−
Ext.onReady(function(){
 
−
Ext.fly("send").on("click", function(){
 
−
// When the "send" button is clicked, emit a "message" event to the server containing a chat message
 
−
socket.emit("message", Ext.fly("comment").getValue());
 
−
});
 
 
});
 
});
 +
 +
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>
−
</head>
 
−
<body>
 
−
<ul id="messages">
 
−
</ul>
 
  
−
<p>
 
−
<textarea id="comment"></textarea>
 
−
<button id="send">Send Comment</button>
 
−
</p>
 
 
</body>
 
</body>
 
</html>
 
</html>
 
</source>
 
</source>
  
−
''Note:'' This example passes strings as the event data, but you can pass any JavaScript datatype, including object literals.
+
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>
  
−
To see this in action, save these two files in the same directory, cd over to the directory, and start the server:
+
Rooms are managed on the server and are invisible to clients.
  
−
<source lang="bash">$ node chat.js</source>
+
== Resources ==
  
−
Fire up your favorite browser and navigate to http://localhost:3456/. Open the page in two windows.  Violà: you have your (very basic) chat client!
+
* https://socket.io/docs/v4/
 +
* Rooms documentation: https://socket.io/docs/v4/rooms/
  
−
[[Category:Module 7]]
+
[[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.

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_server events
  • 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:

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:

  • io.emit(...) → send to all clients
  • socket.broadcast.emit(...) → send to all except sender
  • io.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