Challenge 2: Track Connected Clients With Logging — Possible Solution ==================================================================== import { WebSocketServer } from "ws"; const wss = new WebSocketServer({ port: 8080 }); const clients = new Set(); wss.on("connection", (socket) => { clients.add(socket); console.log(`Client connected. Current count: ${clients.size}`); socket.on("message", (data) => { socket.send(data.toString()); // echo, as in Challenge 1 }); socket.on("close", () => { clients.delete(socket); console.log(`Client disconnected. Current count: ${clients.size}`); }); socket.on("error", (err) => { console.error("Socket error:", err); }); }); console.log("Echo server with client tracking listening on port 8080"); WHY THIS WORKS -------------- - A Set is a natural fit for tracking connected sockets: adding the same socket twice is a no-op (Sets only store unique values), and removing a specific socket via clients.delete(socket) is a simple, direct operation — no need to search through an array for a matching index. - clients.add(socket) happens INSIDE the "connection" handler, at the moment a client's socket object is created — this is the earliest point the client can be tracked. - clients.delete(socket) happens inside THAT SAME socket's "close" handler, not some later cleanup pass — this guarantees the client is removed from tracking at the exact moment its connection actually ends, keeping clients.size always accurate. - Logging clients.size right after both add() and delete() gives a real-time view of how many clients are currently connected, which is exactly the kind of visibility a raw ws server doesn't give you for free — you have to build it yourself, unlike some higher-level libraries that track this automatically (previewed in the next chapter). - This same "clients" Set is the foundation the broadcast pattern in Challenge 3 builds directly on top of.