socketio / socketio/socket.io

Socket recovery works only once

Open
#4,880 9 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

needs investigation
Dominant language
TypeScript
Stars
63.2k
Forks
10.3k
Avg merge
11d 20h
Merged PRs (30d)
2

Description

Describe the bug
I have multiplayer game/chat site where users are sometimes disconnected due to bad internet connection. With new socket.io now I use opton for socket recovery. I have created a button on page to deliberately close client's connection to socket. When I did it first time, socket was recovered and everything was fine. After second attempt to disconnect, socket is not recovered

To Reproduce

Please fill the following code example:

Socket.IO server version: 4.7.2

Server

MyAppHttp.js (simplified)

let express = require('express');
let app = express();
let bodyParser = require('body-parser');
const fs = require('fs');

const privateKey = fs.readFileSync(__dirname + "/../pkey.pem", "utf8");
const certificate = fs.readFileSync(__dirname + "/../pcert.pem", "utf8");
const credentials = {
	key: privateKey,
	cert: certificate
};
let http = require('https').createServer(credentials, app);
let options = {
	cors: {
		origin: "*"
	},
	connectionStateRecovery: {
		maxDisconnectionDuration: 2 * 60 * 1000,
		skipMiddlewares: true,
	}
};
let io = require('socket.io')(http, options);
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
	extended: true
}));

exports.app = app;
exports.io = io;
exports.http = http;

main.js (simplified)

const myAppConn = require('./system/MyAppHttp');
const Constants = require("./system/Constants");
let notifierUser = require("./classes/notifier/NotifierUser");
let appErrorLogger = require("./system/AppErrorLogger")
new appErrorLogger("notifier");

let somethingChanged = false;
let users = {};
let disconnects = {};

myAppConn.io.on('connection', (socket) => {
	if (socket.recovered) {
		console.log('recovery was successful: ' + socket.id);
		if (disconnects.hasOwnProperty(socket.id)) {
			clearTimeout(disconnects[socket.id]);
			delete disconnects[socket.id];
		}
		somethingChanged = true;
	} else {
		console.log('recovery NOT successful');
		users[socket.id]=....
		...
	}
	socket.on('disconnect', () => {
		console.log("Disconnecting " + socket.id);
		disconnectUser(socket);
	});
});
myAppConn.http.listen(Constants.PORT_NOTIFIER, () => {
	console.log('listening on *:' + Constants.PORT_NOTIFIER);
});
function disconnectUser(socket) {
	if (!disconnects.hasOwnProperty(socket.id)) {
		disconnects[socket.id] = setTimeout(() => {
			...
			if (users.hasOwnProperty(socket.id)) {
				delete (users[socket.id]);
				console.log("deleted user " + socket.id);
			}
			somethingChanged = true;
		}, 30000);
	}

}

Socket.IO client version: 4.7.2

Client
(simplified)

class Notifier {
	constructor() {
		this.socket = null;
		this.tm = null;
		this.connectionObject = {
			reconnectionAttempts: Infinity,
			reconnectionDelay: 10000,
			reconnectionDelayMax: 10000,
			randomizationFactor: 0.5,
			timeout: 20000,
			upgrade: false,
			query: ""
		};
	}

	connect() {

		this.socket = io(vojjin.nodeserver + ":" + Constants.PORT_NOTIFIER, this.connectionObject);

		this.socket.on('connect', () => {
			console.log("recovered?", this.socket.recovered);
			if (this.socket.recovered) {
				// any event missed during the disconnection period will be received now
			} else {
				// new or unrecoverable session
			}
			$("#info").text("CONNECTED");
		});
		this.socket.on('disconnect', () => {
			$("#info").text("NOT CONNECTED");

		});
	}
}

let notifier = new Notifier();
$(document).ready(function () {
	notifier.connect();
	$("#info").on("click", function () {
		//click on info text will disconnect
		if (notifier.socket.io.engine) {
			notifier.socket.io.engine.close();
		}

	});
});

Expected behavior
I expected to recover again. But no, it is not recovering, rather it is giving new socket id after second disconnection.

Platform:

  • Device: Mac Studio M1 ultra
  • OS: MacOS SOnoma 14.1.1

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the connectionStateRecovery setup in MyAppHttp.js, then follow the connection and disconnect handlers in main.js and the Notifier client’s connect() method. Reproduce repeated client-side engine.close() calls with Socket.IO 4.7.2 and compare socket.recovered and socket.id after each reconnect. Done means repeated disconnections recover as expected or the failure is documented with a confirmed cause.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, nodejs
Domain
networking
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.