- Introduction
- Initial Setup
- Installation
- Server Initialization
- Client Initialization
- Emitting Events
- Listening to Events
- Broadcasting
- Rooms
- Cheatsheet
- Code Example
Introduction
Socket.IO is a library that enables low-latency, bidirectional and event-based communication between a client and a server.
It is built on top of the WebSocket protocol and provides additional guarantees like fallback to HTTP long-polling or automatic reconnection.
Although Socket.IO indeed uses WebSocket for transport when possible, it adds additional metadata to each packet. That is why a WebSocket client will not be able to successfully connect to a Socket.IO server, and a Socket.IO client will not be able to connect to a plain WebSocket server either.
Socket.IO is composed of two parts:
A server that integrates with (or mounts on) the Node.JS HTTP Server socket.io
A client library that loads on the browser side socket.io-client
Initial Setup
Installation
You will need to install socket for both the server and the client.
To install for the server:
npm install socket.io
To install for the client:
npm install socket.io-client
Server Initialization
For your server side, you have to set up your node/express server first.
const io = require("socket.io")();
// or
const { Server } = require("socket.io");
const io = new Server();
The server instance emits one event which is the connection string. The first argument is the socket instance.
io.on("connection", (socket) => {
console.log(socket.id); // ojIckSD2jqNzOqIrAGzL
});
Client Intialization
To get the io object for the client you can do either of the following:
Add script to html:
<script src="/socket.io/socket.io.js"></script>
Import:
// ES6 import or TypeScript
import { io } from "socket.io-client";
// CommonJS
const io = require("socket.io-client");
Initialize the connection:
If the frontend is served differently from the domain of your server, you might have to use CORs on the server.
Emitting Events
The Socket.IO API is inspired from the Node.js EventEmitter, which means you can emit events on one side and register listeners on the other:
To emit events you use emit() where you pass in the name of the event and an argument:
// server-side
io.on("connection", (socket) => {
socket.emit("hello", "world");
});
// client-side
socket.on("hello", (arg) => {
console.log(arg); // world
});
What's happening here? Once a connection is made, the socket emits an event called "hello", which contains the string "world" as an argument. The client listens for the event "hello" and in doing so, it logs the value of the arg to the console.
This works the other way around as well:
// server-side
io.on("connection", (socket) => {
socket.on("hello", (arg) => {
console.log(arg); // world
});
});
// client-side
socket.emit("hello", "world");
Listening to Events
Most of the time, you will be using the on() method to listen to events where you pass in an event name and a listener function at the end.
Here are some other common Event Listeners:
socket.once(eventName, listener) - Adds a one-timelistener function for the event named eventName
socket.once("details", (...args) => {
// ...
});
socket.off(eventName, listener) - Removes the specified listener from the listener array for the event named eventName.
const listener = (...args) => {
console.log(args);
}
socket.on("details", listener);
// and then later...
socket.off("details", listener);
socket.removeAllListeners([eventName]) - Removes all listeners, or those of the specified eventName.
// for a specific event
socket.removeAllListeners("details");
// for all events
socket.removeAllListeners();
Read more about listeners here: Listening to events | Socket.IO
Broadcasting
Broadcasting is a server-only feature that emits an event to everyone but the user themselves.
You simply add the broadcast function before your emitter:
io.on("connection", (socket) => {
socket.broadcast.emit("hello", "world");
});
In certain cases, you may want to only broadcast to clients that are connected to the current server. You can achieve this with the local flag:
io.local.emit("hello", "world");
If you want to broadcast to specific people, you will need to create a room.
Rooms
A room is an arbitrary channel that sockets can join and leave. It can be used to broadcast events to a subset of clients:
You can call join to subscribe the socket to a given channel:
io.on("connection", socket => {
socket.join("some room");
});
And then simply use to or in (they are the same) when broadcasting or emitting:
io.to("some room").emit("some event");
You can emit to several rooms at the same time:
io.to("room1").to("room2").to("room3").emit("some event");
In that case, a union is performed: every socket that is at least in one of the rooms will get the event once (even if the socket is in two or more rooms).
To leave a channel you call leave in the same fashion as join.
Cheatsheet
Server Side Cheatsheet
io.on("connection", (socket) => {
// basic emit
socket.emit(/* ... */);
// to all clients in the current namespace except the sender
socket.broadcast.emit(/* ... */);
// to all clients in room1 except the sender
socket.to("room1").emit(/* ... */);
// to all clients in room1 and/or room2 except the sender
socket.to("room1").to("room2").emit(/* ... */);
// to all clients in room1
io.in("room1").emit(/* ... */);
// to individual socketid (private message)
io.to(socketId).emit(/* ... */);
// to all clients on this node (when using multiple nodes)
io.local.emit(/* ... */);
// to all connected clients
io.emit(/* ... */);
});
Client Side Cheatsheet
// basic emit
socket.emit(/* ... */);
// with acknowledgement
socket.emit("question", (answer) => {
// ...
});
Reserved EventNames
connect
connect_error
disconnect
disconnecting
newListener
removeListener
Code Example
Server Side Code
const express = require("express");
const app = express();
const http = require("http");
const { Server } = require("socket.io");
const cors = require("cors");
app.use(cors());
const server = http.createServer(app);
const io = new Server(server, {
cors: {
origin: "http://localhost:3000",
methods: ["GET", "POST"],
},
});
io.on("connection", (socket) => {
console.log(`User Connected: ${socket.id}`);
socket.on("join_room", (data) => {
socket.join(data);
});
socket.on("send_message", (data) => {
socket.to(data.room).emit("receive_message", data);
});
});
React Client Side Code
import "./App.css";
import io from "socket.io-client";
import { useEffect, useState } from "react";
const socket = io.connect("http://localhost:3001");
function App() {
//Room State
const [room, setRoom] = useState("");
// Messages States
const [message, setMessage] = useState("");
const [messageReceived, setMessageReceived] = useState("");
const joinRoom = () => {
if (room !== "") {
socket.emit("join_room", room);
}
};
const sendMessage = () => {
socket.emit("send_message", { message, room });
};
useEffect(() => {
socket.on("receive_message", (data) => {
setMessageReceived(data.message);
});
}, [socket]);
return (
<div className="App">
<input
placeholder="Room Number..."
onChange={(event) => {
setRoom(event.target.value);
}}
/>
<button onClick={joinRoom}> Join Room</button>
<input
placeholder="Message..."
onChange={(event) => {
setMessage(event.target.value);
}}
/>
<button onClick={sendMessage}> Send Message</button>
<h1> Message:</h1>
{messageReceived}
</div>
);
}
export default App;
Kommentare