I am using this code for socket cluster.
HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Worker Socket Connection</title>
</head>
<body>
<button id="connect_socket" onclick="connectSocket()" type="submit">
connect
</button>
<br>
<br>
<textarea cols="50" rows="15" id="message"></textarea>
</div>
<!-- make sure you're using the same socket version in server and client -->
<script src="https://cdn.socket.io/4.6.0/socket.io.min.js" integrity="sha384-c79GN5VsunZvi+Q/WObgk2in0CbZsHnjEqvFxC5DxHn9lTfNce2WW6h2pH6u/kF+" crossorigin="anonymous"></script>
<script src="main.js"></script>
</body>
</html>
Client side code:
var log = (mgs, ctx) => {
ctx = ctx ?? '===';
let messageBox = document.getElementById('message')
messageBox.innerHTML += `${ctx}: ${mgs}` + "\n"
}
var connectSocket = () => {
const socket = io({
extraHeaders: {
"my-token": "token-goes-here"
},
});
// client-side
socket.on("connect", () => {
log(socket.id, 'socket_id');
log(socket.connected, 'connection_status');
socket.on("server_data", (arg) => {
log(arg, 'server_data');
});
});
socket.on("connection_error", (err) => {
log('error', err);
})
socket.on("disconnect", (reason) => {
log('socket disconnected', reason)
log(socket.id, 'socket_id'); // undefined
log(socket.connected, 'connection_status'); // false
});
socket.on("connect_error", () => {
log('connect_error & reconnect');
socket.connect();
});
};
Server side code:
import cluster from "cluster"
import express from "express"
import cors from "cors"
import path from "path"
import os from "os"
import { Server } from "socket.io"
import { setupMaster, setupWorker } from "@socket.io/sticky"
import { createAdapter, setupPrimary } from "@socket.io/cluster-adapter"
let numCPUs = os.cpus().length
const __dirname = path.resolve(path.dirname(''));
const PORT = 3000;
const HOST = '0.0.0.0';
if (cluster.isPrimary) {
console.log(`Master ${process.pid} is running`);
const app = express()
// setup sticky sessions
setupMaster(app, {
loadBalancingMethod: "least-connection",
});
// setup connections between the workers
setupPrimary();
// needed for packets containing buffers (you can ignore it if you only send plaintext objects)
// Node.js > 16.0.0
cluster.setupMaster({
serialization: "advanced",
});
// app.listen(+PORT, HOST, () => { })
for (let i = 0; i < numCPUs; i++) {
cluster.fork();
}
cluster.on("exit", (worker) => {
console.log(`Worker ${worker.process.pid} died`);
// cluster.fork();
});
} else {
console.log(`Worker ${process.pid} started`);
const app = express();
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(cors());
app.use(function (req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
next();
});
app.use(express.static(__dirname + "/static/"));
// const httpServer = http.createServer();
console.log(`'HTTP server started' on port ${PORT}`);
const server = app.listen(+PORT, HOST, () => { });
app.get('/', async (req, res) => {
res.sendFile(__dirname + '/static/index.html');
});
const io = new Server(server,{
cors: {
origin: "*",
methods: ["GET", "POST"]
},
maxHttpBufferSize: 1e10,
pingInterval: 10000, // 10 seconds
pingTimeout: 60000, // 60 seconds
})
// use the cluster adapter
io.adapter(createAdapter());
// setup connection with the primary process
setupWorker(io);
io.on("connection", function (socket) {
console.log("Made socket connection");
console.log(socket.handshake.headers);
socket.on("disconnect", () => {
console.log('disconnected', socket.id);
});
});
}
But with this code I couldn't connect the socket. It always show the transport_error or ws://localhost:3000/socket.io/ failed. If I use "transport": ["websocket"]. Then it connects perfectly but I couldn't set the headers. I need to send headers too from client to server. Please help me how to solve and work with it. Reference code: https://socket.io/docs/v4/cluster-adapter/.
I will really appreciate if I get the solution. Thanking you in advance.