socketio / socket.io

Realtime application framework (Node.JS server)
https://socket.io
MIT License
61.2k stars 10.11k forks source link

Transport close after 1 hour in socket.io 3.1.2 #3858

Closed aliindia closed 2 years ago

aliindia commented 3 years ago

Describe the bug Transport close after 1 hour in socket.io 3.1.2

Socket.IO server version: 3.1.2

Server

const cluster = require("cluster");
const express = require('express');
const bodyParser = require('body-parser');
const http = require('http');
const { Server } = require("socket.io");
const redisAdapter = require("socket.io-redis");
const numCPUs = require("os").cpus().length;
const { setupMaster, setupWorker } = require("@socket.io/sticky");
var cors = require('cors');
require('newrelic');
var admin = require("firebase-admin");
var serviceAccount = require("./abc-xyz.json");
if (!admin.apps.length)
{
  admin.initializeApp({
    credential: admin.credential.cert(serviceAccount)
  });   
}

var redisHost = '127.0.0.1';
var redisPort = 6379;

if (cluster.isMaster) {
  console.log(`Master ${process.pid} is running`);

  const httpServer = http.createServer();
  setupMaster(httpServer, {
    loadBalancingMethod: "least-connection", // either "random", "round-robin" or "least-connection"
  });
  httpServer.listen(3000);

  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 port = process.env.PORT || 5000;
  const app = express();
  // require('newrelic');
  var corsOptions = {
    origin: /foniqca\.com$/,
    methods: 'OPTIONS, GET, POST',
    allowedHeaders:'accept, accept-encoding, authorization, content-type, dnt, origin, user-agent, x-csrftoken, x-requested-with, tenantId',
    maxAge:604800000, // 7 Days, 3600000 = 1 hour //maxAge:3600,
    optionsSuccessStatus: 200 // some legacy browsers (IE11, various SmartTVs) choke on 204
  }
  // corsOptions = {}
  app.use(cors(corsOptions))

  app.use(bodyParser.urlencoded({extended:true}))
  app.use(bodyParser.json())

  const httpServer = http.createServer(app);
  // const io = new Server(httpServer);
  const io = new Server(httpServer);
  io.adapter(redisAdapter({ host: redisHost, port: redisPort }));
  setupWorker(io);

  httpServer.listen(port, ()=> {console.log(`Listening on port ${port}`)})

  app.get('/', (req, res) => {
  res
    .status(200)
    .send('Welcome to WS.')
    .end();
});

Socket.IO client version: 3.1.2

Client

import io from "socket.io-client";

 socket = io(config.socketEndpoint+'/'+subdomain,{
        transports: ["websocket"],
        query: {token: idToken},
        forceNew: false,
        reconnection: true,
        reconnectionDelay: 3000,
        reconnectionDelayMax: 5000,
        reconnectionAttempts: Infinity
      });

      socket.on('connect', function() {
        socket.emit('join', subdomain)
        socket.emit('join', subdomain+'_'+uid)
      });

      socket.on("disconnect", (reason) => {
        console.log('disconnect.reason',reason);
        if (reason === "io server disconnect" || reason === "transport close") {
          // the disconnection was initiated by the server, you need to reconnect manually
          socket.connect();
        }
        // else the socket will automatically try to reconnect
      });

      socket.on('connect_error', function(error){
          console.log('connection error: ' + error);
      }); 

      socket.on('connect_timeout', function(){
          console.log('connection timeout');
      });

      socket.on('reconnect', function(){
          console.log('reconnect');
      });

      socket.on('reconnect_attempt', function(){
          console.log('reconnect attempt');
      });

      socket.on('reconnect_failed', function(){
          console.log('reconnect_failed');
      });

      socket.on('reconnect_error', function(){
          console.log('reconnect_error');
      });

      socket.on('reconnecting', function(){
          console.log('reconnecting');
      });

      socket.on('ping', function(){
          console.log('ping');
      });

      socket.on('pong', function(ms){
          console.log('pong ' + ms + "ms");
      });

      setInterval(() => {
        const start = Date.now();

        // volatile, so the packet will be discarded if the socket is not connected
        socket.volatile.emit("ping", () => {
          const latency = Date.now() - start;
          console.log('latency ' + latency + "ms");
        });
      }, 5000);

Expected behavior It should not close transport after 1 hour

image

darrachequesne commented 3 years ago

Hi! Exactly 1 hour sounds like a timeout of something between the client and the server.

In any case, please note that you can't expect that your connection will stay up for an indefinite amount of time.

See also: https://socket.io/docs/v4/troubleshooting-connection-issues/

aliindia commented 3 years ago

Hi! Exactly 1 hour sounds like a timeout of something between the client and the server.

In any case, please note that you can't expect that your connection will stay up for an indefinite amount of time.

See also: https://socket.io/docs/v4/troubleshooting-connection-issues/

Can please guide me how to re-connection the closed transport in this case as we are working with ReactJs and user are continue working with current UI will gets message without refeshing their page.

darrachequesne commented 3 years ago

@aliindia there is nothing to do, the client will automatically reconnect (unless you use the option reconnection: false).

Documentation: https://socket.io/docs/v4/client-initialization/#reconnection

darrachequesne commented 2 years ago

Closed due to inactivity, please reopen if needed.

redouaneboukamir commented 6 months ago

I have the exact same error and also after 1hour my connexion automatically disconnect

python :

app = Flask(name) app.secret_key = os.urandom(24) app.config['SESSION_PERMANENT'] = True app.config['SESSION_TYPE'] = 'filesystem' app.permanent_session_lifetime = timedelta(days=7) socketio = SocketIO(app, async_mode='eventlet', cors_allowed_origins="*", logger=True, max_http_buffer_size=1e8, engineio_logger=True, ping_timeout=180000, ping_interval=90000, compress=True)

                javascript : 

                          socket = io.connect(location.protocol + "//" + document.domain + ":" + location.port, {
        query: {
          socketId: existingSocketId
        },
        reconnection: true,
        reconnectionAttempts: Infinity,
        reconnectionDelay: 5000,
        pingInterval: 90000,
        pingTimeout: 180000
      });
darrachequesne commented 6 months ago

@redouaneboukamir hi! It sounds like something between the client and the server is closing the connection after 1 hour.

See also: https://socket.io/docs/v4/troubleshooting-connection-issues/#something-between-the-server-and-the-client-closes-the-connection

That being said, while a bit annoying, it is your duty to handle those temporary disconnections and sync the state of the client upon reconnection.

redouaneboukamir commented 6 months ago

Yes i thought so, i did all i found to keep up the connection between the server and the client but all i saw on forum, documentation, stackoverflow, i tried and nothing helped. It can be because of my server or something ? because my app is hosted by replit VM