socketio / socketio/socket.io

Socket.io connects and disconnects only for some clients resulting in package lost / unreliability

Open
#4,298 11 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

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

Description

Describe the bug
A clear and concise description of what the bug is.
We have an nodejs websocket server with 3k+ concurrent connections. A few segment of clients disconnect and reconnect every few seconds/minutes.

We trigger the connection by joining to a room.

        roomsOnline.add(socket.handshake.query.roomId);
        socket.join(socket.handshake.query.roomId);

We use AWS ELB and their support says the load balancer has no problem.

image

On my machine i stay connected with the exact same roomId.

However his connection on the server end looks like this where it disconnects and reconnects. When we try to send the client a message using io.to(roomId).emit() it will only few of the messages instead of every message emitted

image

One of the clients that saw this behavior we tested with a different browser source from another websocket app and the messages work every time to his computer. The same client also had high speed spectrum internet.

To Reproduce

Our server settings - version 4.4.1

 allowEIO3: true, // false by default
    pingInterval: 9000,
    pingTimeout: 15000,

Server


const server = process.env.USE_HTTPS
    ? require("https").createServer(
          {
              cert: fs.readFileSync(process.env.TLS_CERT),
              key: fs.readFileSync(process.env.TLS_KEY),
          },
          app,
      )
    : require("http").createServer(app);

const { Server } = require("socket.io");

// https://stackoverflow.com/questions/48648555/understanding-socket-io-ping-interval-timeout-settings
const io = new Server(server, {
    // transports: ["polling", "websocket"],
    allowEIO3: true, // false by default
    pingInterval: 9000,
    pingTimeout: 15000,

    cors: {
        origin: "*",
        methods: [
            "GET",
            "POST",
            "OPTIONS",
            "HEAD",
            "PUT",
            "PATCH",
            "POST",
            "DELETE",
        ],
    },
});

Socket.IO client version: x.y.z

Client

    <script src="/socket.io/socket.io.js"></script>

    let socket = io({
          query: {
            roomId: last_part
          }
        });

Expected behavior
Expect all clients to stay connected

Platform:

  • Device:
  • CPU Name: AMD Ryzen 5 5600X 6-Core Processor
    CPU Speed: 3700MHz
  • OS: Windows, Chrome/OBS

Additional context
I added a disconnect protocol which helped some clients that were international, but few clients still seeing this behavior

Server
let disconnectCheck = setInterval(() => {
            socket
                .timeout(16000)
                .emit(
                    "heart_beat_check_server",
                    "beating",
                    { running: new Date() },
                    (err, payload) => {
                        console.log(
                            "HEART_BEAT_PAYLOAD",
                            payload,
                            socket.handshake.query.roomId,
                        );
                        if (
                            err &&
                            payload &&
                            payload.version &&
                            payload.version >= 3
                        ) {
                            // the client did not acknowledge the event in the given delay
                            console.error(
                                "HEARTBEAT_ERROR_TIMEOUT",
                                socket.handshake.query.roomId,
                            );
                            socket.disconnect(true);
                        } else {
                        }
                    },
                );
        }, 17000);

Client
   socket.on("heart_beat_check_server",  (_, __, callback) => {
            console.error("heart_beat_check_server_client")
            callback({ roomdId: last_part, version: browserVersion })
        });

socket.on("disconnect", (reason) => {
          console.error("DISCONNECTED ", reason)
          if (reason === "io server disconnect" || reason === "io client disconnect" || reason === "ping timeout") {
            // the disconnection was initiated by the server, you need to reconnect manually
            socket.connect();
          }
          // else the socket will automatically try to reconnect
        });

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 server and client Socket.IO snippets, including the room join, heartbeat, reconnect handling, and ping settings. Compare the disconnect logs with the reported client and server behavior; done means identifying the cause of the intermittent disconnects and ensuring room broadcasts are not lost for affected clients.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, node.js
Domain
backend, networking
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.