Real time data transfer between client and server using Socket.IO

Real time data transfer between client and server using Socket.IO

Introduction

This article explains socket.io connection between client and server, the main use case and how to get started. This content is useful for the beginner as well as for the experienced developer who will create the application in a standard and organized way.

What is Socket IO?

Socket.io is a JavaScript library that works similarly to WebSockets. Data transfer is done via an open connection allowing for real-time data exchange. Each connection, also known as a socket, consists of two parts: The server side and the client side. Socket.io makes use of Engine.io to achieve server-side connection with Engine. io-client for the client side.

It consists of both the client side and the server side, with the server-side handling different connections and information dispersion

Why use Socket IO?

Explain you about the use of socket IO using the example. Let's assume that you are working on a chat application. When user A is typing something then user B should know that A is typing (similar to gtalk of Facebook messenger). If you will use HTTP calls then "B" will never be able to see the actual status of the other person because of the delay. So what we can use is sockets so that when user A is typing anything then his device will send only one data packet which will just notify the server that he is typing and will be delivered to user B, this process is fast (almost real-time) and will reduce the data transfer alsoEndFragment.

Installation and setup of socket Io between React and Node.js

Because Socket.io needs both a server-side and a client side to achieve a connection, we will be making installations for both (server and client) starting with the server side and then moving to the client side.

Ensure that you have Node.js and node package manager (npm) already installed in your system. If not, proceed to the Node.js website to learn more about installation.

In your command line, run the following command:

Create a root folder and server.js file

$> mkdir SocketIoClientServerConnection
$> cd SocketIoClientServerConnection
$> touch server.js

Run the below command to install the package dependency:

The current directory should be SocketIoClientServerConnection

npm install express Socket.io http

The above command creates a node_moduls folder in the current directory and a package-lock.json file is created.

Server-side

Setup server.js file:

const express = require("express");
const http = require("http");
const io = require("socket.io");
const bodyParser = require("body-parser");
const path = require("path");

const fs = require("fs");

const routes = require("./server/routes");
const config = require("./server/config.js");

class Server {
  constructor() {
    this.port = 5008;
    this.app = express();

    this.httpServer = http.createServer(this.app);
    this.socket = io(this.httpServer);
  }
  appconfig() {
    this.app.use(express.json());
    this.app.use(express.urlencoded({ extended: true }));

    this.app.use(express.static(path.join(__dirname, "build")));
    new config(this.app);
  }

  includeRoutes() {
    new routes(this.app, this.socket).routesConfig();
  }

  start() {
    this.appconfig();
    this.includeRoutes();

    this.httpServer.listen(8080, () => {
      console.log("server started on 8080 port");
    });

    this.httpsServer.listen(443, () => {
      console.log("server started on 443 port");
    });
  }
}

const server = new Server();
server.start();

Setup routes.js and config.js file in a server folder

routes.js

class Routes {
  constructor(app, socket) {
    this.io = socket;
    this.app = app;
  }

  routesConfig() {
    this.appRoute();
    this.registerSocketEvent();
  }

  appRoute() {
    this.app.get("/", (index, response) => {
      response.render("index");
    });

    // ---- specify all other routes
  }

  registerSocketEvent() {
    this.io.on("connection", (socket) => {
      this.globalSocket = socket;
      socket.on("socket_connection", (cb) => {
        cb("Socket IO Connection Established");
        return;
      });
    });

    // ..... Listen Other socket connection as above  and take action
  }
}

module.exports = Routes;

Set up config.js file to render the view page.

class Config {
  constructor(app) {
    //setting .html as the default template extention
    app.set("view engine", "html");

    // Initilization the ejs template engine
    app.engine("html", require("ejs").renderFile);

    //Telling express where it can find the templates
    app.set("views", __dirname + "/../views");

    // Files
    app.use(require("express").static(require("path").join("public_data")));
  }
}

module.exports = Config;

Client side

Create a src folder that contains React code. Below is an example of how to connect clients with react.

src/index.js

import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
import io from "socket.io-client";

const socket = io();

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  <React.StrictMode>
    <App socket={socket} />
  </React.StrictMode>
);
reportWebVitals();

Needs to install socket.io-client package to set the connection of socket IO in the client side. Create an instance and pass it to the app.js where we will use the socket.

src/app.js

import logo from "./logo.svg";
import "./App.css";
import React, { useEffect, useState } from "react";

function App({ socket }) {
  const [title, setTitle] = useState(null);

  useEffect(() => {
    socket.on("connect", () => {
      socket.emit("socket_connection", (data) => {
        setTitle(data);
      });
    });
  }, []);

  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          {title}
        </a>
      </header>
    </div>
  );
}

export default App;

socket.on("connect", () => {socket.emit("socket_connection", (data) => { setTitle(data); }); });

once socket.emit("socket_connection") line executed then it will emit a connection with a string name and try to find the listener of the same string name in a complete application, for example,

Once the server start and we rendered that same application in the browser then

It executed the above useEffect, it executed the socket.emit()

and the written listener socket.on("socket_connection") in server.js get executed, then UI received the response if any call back is there.

Socket connection and disconnection

In Short, if we emit a connection on the client side then we have to listen to the same connection on the server side or vice versa.

NOTE: Make sure .emit("string1") should be the same as .on("string1").

The call-back mechanism of the socket connection is available on GitHub.