Web Sockets - Socket.io

Comprehensive Guide to Socket.IO

Socket.IO enables real-time, bidirectional, and event-based communication between the browser and the server. It has two main components: a client-side library running in the browser and a server-side library for Node.js.


Table of Contents

  1. Prerequisites

  2. Setting Up the Server

    • Initializing the Project

    • Installing Dependencies

    • Creating the Server

  3. Setting Up the Client

    • Creating a React App

    • Creating the Client Component

  4. Understanding the Code

    • Server-Side Code

    • Client-Side Code

  5. Socket.IO Concepts

    • Events

    • Rooms

    • Broadcasting

  6. Running the Application

  7. Conclusion


Prerequisites

  • Node.js and npm installed on your system.

  • Basic knowledge of JavaScript and Node.js.

  • A code editor, such as Visual Studio Code.


Setting Up the Server

Initializing the Project

First, create a new directory for your project and initialize it with npm:

mkdir socketio-app
cd socketio-app
npm init -y

Installing Dependencies

Install the necessary dependencies: Express and Socket.IO.

npm install express socket.io cors

Creating the Server

Create a file named server.js and add the following code to set up your Socket.IO server:

import express from "express";
import { createServer } from "http";
import { Server } from "socket.io";
import cors from "cors";

const app = express();
const server = createServer(app);

app.use(cors());

const io = new Server(server, {
  cors: {
    origin: "*",
  },
});

app.get("/", (req, res) => {
  res.send("Hello World");
});

io.on("connection", (socket) => {
  console.log("A user connected");
  console.log(socket.id);

  socket.emit("me", `Hi, ${socket.id}, welcome to the app`);
  socket.broadcast.emit("new-user", `New user joined ${socket.id}`);

  socket.on("message", ({ data, room }) => {
    if (!room) {
      socket.broadcast.emit("message", data);
    } else {
      io.to(room).emit("message", data);
    }
  });

  socket.on("create-room", (roomName) => {
    socket.join(roomName);
  });
});

server.listen(3000, () => {
  console.log("Server is running on port 3000");
});

Setting Up the Client

Creating a React App

If you don't have a React app set up yet, you can create one using Create React App:

npx create-react-app client
cd client
npm install socket.io-client

Creating the Client Component

Replace the content of src/App.js with the following code:

import React, { useEffect, useMemo, useState } from "react";
import { io } from "socket.io-client";
import "./App.css";

function App() {
  const [text, setText] = useState("");
  const [room, setRoom] = useState("");
  const [createRoom, setCreateRoom] = useState("");
  const [socketID, setSocketID] = useState("");
  const socket = useMemo(() => io("http://localhost:3000"), []);

  const sendMessage = () => {
    socket.emit("message", { data: text, room });
  };

  const createRoomHandler = () => {
    socket.emit("create-room", createRoom);
  };

  useEffect(() => {
    socket.on("connect", () => {
      console.log("Connected to server", socket.id);
      setSocketID(socket.id);
    });

    socket.on("me", (data) => {
      console.log("Me", data);
    });

    socket.on("new-user", (data) => {
      console.log("New user", data);
    });

    socket.on("message", (data) => {
      console.log("Message", data);
    });
  }, [socket]);

  return (
    <div className="App">
      <header className="App-header">
        <h4>Socket.io id --- {socketID}</h4>
        <input
          type="text"
          placeholder="Enter any message"
          onChange={(e) => setText(e.target.value)}
        />
        <input
          type="text"
          placeholder="Enter any Room"
          onChange={(e) => setRoom(e.target.value)}
        />
        <button onClick={sendMessage}>Send</button>
        <input
          type="text"
          placeholder="Create any Room"
          onChange={(e) => setCreateRoom(e.target.value)}
        />
        <button onClick={createRoomHandler}>Create</button>
      </header>
    </div>
  );
}

export default App;

Understanding the Code

Server-Side Code

  • Setting Up Express and Socket.IO: We import the necessary modules, create an Express application, and set up a Socket.IO server that allows cross-origin requests from any domain.

  • Handling Connections: When a client connects, we log the connection and send a welcome message to the client. We also notify all other clients about the new user.

  • Handling Messages: We listen for message events from the client. If a room is specified, the message is sent to that room; otherwise, it is broadcast to all clients except the sender.

  • Creating Rooms: We listen for create-room events from the client and add the client to the specified room.

Client-Side Code

  • Setting Up Socket.IO Client: We use useMemo to create a single instance of the Socket.IO client when the component mounts.

  • Handling User Input: We maintain state for the message text, room name, and socket ID. Input fields and buttons are provided to allow the user to send messages and create rooms.

  • Listening for Events: We listen for various events from the server (e.g., connection, me, new-user, message) and handle them appropriately.


Socket.IO Concepts

Events

Socket.IO allows communication through events. You can send and receive events from both the server and the client.

  • socket.emit(eventName, data): Sends an event to the server or client with the specified event name and data.

  • socket.on(eventName, callback): Listens for an event with the specified event name and executes the callback when the event occurs.

Rooms

Rooms are arbitrary channels that sockets can join and leave. They are useful for broadcasting messages to a subset of clients.

  • socket.join(roomName): Adds the socket to a room.

  • io.to(roomName).emit(eventName, data): Sends a message to all sockets in the specified room.

Broadcasting

Broadcasting sends a message to all connected clients except the sender.

  • socket.broadcast.emit(eventName, data): Sends a message to all clients except the sender.

  • io.emit(eventName, data): Sends a message to all connected clients, including the sender.


Running the Application

Start the Server

Navigate to the directory containing server.js and start the server:

node server.js

Start the Client

Navigate to the client directory and start the React app:

npm start

Conclusion

This guide covers setting up a basic real-time application using Socket.IO with a Node.js server and a React client. You can build a chat application or any other real-time feature by following these steps. Experiment with the code and extend the functionality as needed to suit your application's requirements.

Instructor: Muhammad Sufiyan

Linkedin: linkedin.com/in/innosufiyan