Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

why socket.disconnect() on client side doesn't fire disconnect event on the server? #2297

Closed
sdrabb opened this issue Nov 4, 2015 · 27 comments
Labels
unable to reproduce We were unable to reproduce the issue

Comments

@sdrabb
Copy link

sdrabb commented Nov 4, 2015

here's my code:

client-side

 var socket = io.connect('http://' + serverAddress ,{ reconnection: false, forceNew: true  }  );

 socket.emit('monitorAddedNotify' , { video: sourceVideo , socketId: socket.id});

 socket.on('disconnectThatSoc', function(){
    socket.disconnect();
});

server-side:

  io.on('connection', function (socket) {
    console.log('a user connected');


    socket.on('disconnect', function () {
        console.log('user disconnected');
    });
 });

the socket.disconnect() method doesn't work why?

@nkzawa
Copy link
Contributor

nkzawa commented Nov 11, 2015

As far as I tested, it works fine. How can we reproduce the issue?

@ventaquil
Copy link

Try to enter page and fast reload by pressing many times F5 button.

@alexandrubau
Copy link

It works fine for me also.

@ventaquil
Copy link

Which browser do you use? I'm using latest Firefox and when I fast reload bage "user disconnected" doesn't working 😞

@nkzawa nkzawa added the unable to reproduce We were unable to reproduce the issue label Jan 17, 2016
@iHaiduk
Copy link

iHaiduk commented Jan 6, 2017

I have the problem too. In these actions, disconnection, but it comes much later than was restarted browser.

Browser: Chrome 55.0.2883.95 (64-bit)
socket.io: "^1.7.2"

@giathinh910
Copy link

Hi @ventaquil. I'm the same trouble that the disconnect event not firing when holding F5. Have you got over this?

@darrachequesne
Copy link
Member

@giathinh910 isn't the disconnect event fired after a given delay (that may be related to pingTimeout / pingInterval options, documented here)?

@giathinh910
Copy link

@darrachequesne My issue is the same as @ventaquil described above "Try to enter page and fast reload by pressing many times F5 button". Usually when you refresh a page socket connection will fire "disconnect" then "connect" again. I rely on these 2 events to update the numbers of online users. However if the page reloading fast enough, the "disconnect" won't fire, which cause some inexistent user socket id added. These unreal people will be removed after pingTimeout of course. Currently I change the way of saving socket id which will only show the online user, not the number of socket and the problem can be solved.

@invincibletrain
Copy link

invincibletrain commented Sep 7, 2017

I handled this problem this way. I've made an emit sender on client which is calling heartbeat on server.

socket.on("heartbeat", function() {
            // console.log('heartbeat called!');
            hbeat[socket.id] = Date.now();
            setTimeout(function() {
                var now = Date.now();
                if (now - hbeat[socket.id] > 5000) {
                    console.log('this socket id will be closed ' + socket.id);
                    if (addedUser) {
                        --onlineUsers;
                        removeFromLobby(socket.id);
                        try {
                            // this is the most important part
                            io.sockets.connected[socket.id].disconnect();
                        } catch (error) {
                            console.log(error)
                        }
                    }
                }
                now = null;
            }, 6000);
        });

I found this code function to call:

io.sockets.connected[socket.id].disconnect();

@madprops
Copy link

madprops commented Mar 15, 2018

This still happens. It doesn't have to be F5/refresh. Opening a tab and closing it soon quickly at a certain stage, causes disconnect to not be triggered. It's hard to reproduce because sockets are very fast, especially when running locally. I noticed opening the tab in the background and having other tabs open helped to reproduce the problem (locally). I think this is an important bug that should be addressed.

@ThatBrianDude
Copy link

Having the same issue here. This is creating ghost games on my game server

@ghost
Copy link

ghost commented Apr 22, 2018

Maybe to manually disconnect the client, you can use a function with some emitting.
I don't know if this'll help, but I think I got something... Maybe...

Client:

function ManualSocketDisconnect() {
    socket.emit("manual-disconnection", socket.id);
    
    socket.close();
    
    console.log("Socket Closed. ");
}

Server:

io.on("connection", function(socket) {
    console.log("User " + socket.id + " Connected. ");
  
    socket.on("manual-disconnection", function(data) {
        console.log("User Manually Disconnected. \n\tTheir ID: " + data);
    });
});

Sorry, but I probably left some holes in my code. I'm no professional. 🙁

@manjotsk
Copy link

manjotsk commented Oct 27, 2018

I am facing the same issue!
I'll be giving the example in ReactJS-ExpressJS.

Here is the situation, which will fire the event, and is encapsulated in componentWillUnmount().

I'll be comparing two events, which i will fire from componentWillUnmount()

  1. newMessage:- this will broadcast message to particular room
  2. disconnect:-(I hoped it will work, but it doesn't) This event listener have call back which will disconnect. I have contained a console.log() just to confirm if the call back hits.

Now, Here we go:-
Client:-

These events are being fired:-

  componentDidMount() {
    console.log(this.props)
    chat.emit('authenticate', {
      token: localStorage.getItem('auth'),
      refreshToken: localStorage.getItem('refresh'),
      projectId: this.props.projectId,
      userId: this.props.userId,
    });
    chat.on('newMessage', (messageData) => {
      console.log('------------newMessageReceived-------------');
      this.props.messageReceived({ messages: this.props.messages, messageData }, () => {
        console.log('callback');
        this.setState({
          messages: this.props.messages
        })
      })
      console.log(messageData);
    })
  }

Following event wont fire.

  componentWillUnmount() {
    chat.emit('disconnect','just disconnect);
  }

The following event will be triggered.(just testing if normal message event emits)

  componentWillUnmount() {
    chat.emit('newMEssage', {
      messageHeader: {
        sender: {
          user: {
            id: this.props.userId,
            name: this.props.name
          }
        }
      },
      messageBody: 'hello',
    });
  }

No Luck

Server:-
Here is the code at the expressJS backend

//Following initializeChatSocket is called in app.js

function initializeChatSocket(server) {
  projects.hasMany(projectTeam, { foreignKey: 'projectId' });

  const io = socketIO(server);
  const chat = io.of('/chat').on('connection', function (socket) {
    console.log(
      '----------------------------------------New Chat Connection Established-------------------------------------------------------------------------'
    );

    socket.auth = false;

    socket.on('authenticate', function (data) {
      console.log('\n\n\n\n', 'authenticate called', '\n\n\n\n', data, '\n\n\n');

      try {
        const dummyReq = {
          headers: {
            refreshtoken: data.refreshToken,
          },
        };
        console.log('\n\n\n\n', 'before verify', '\n\n\n\n');
        const userDetails = verifyJWTToken(dummyReq, data.token);
        console.log('\n\n\n\n', 'after verify', '\n\n\n\n');
        socket.userId = userDetails.userId;
        socket.projectId = data.projectId;

        projectTeam
          .findAll({
            where: {
              [Op.and]: {
                projectId: data.projectId,
                userId: data.userId,
              }
            }
          })
          .then(projects => {
            console.log('\n\n\n\n', JSON.stringify(projects), '\n\n\n\n');
            if (projects.length === 1) {
              socket.auth = true;
              socket.join(socket.projectId);
              console.log('User id:- ${userDetails.userId} linked to project id :- ${socket.projectId}');
            } else {
              console.log('User id:- ${userDetails.userId} not linked to project id :- ${socket.projectId}');
              throw { message: 'User not linked to project' };
            }
          });
      } catch (error) {
        console.log(String(error));

        socket.auth = false;
        socket.disconnect(String(error));
      }
    });

    socket.on('disconnectt', function() {
      console.log('Client Disconnecting'); // This is not being fired :/
      socket.removeAllListeners('newMessage');
      socket.removeAllListeners('disconnect');
      socket.removeAllListeners('authenticate');
      socket.removeAllListeners('connection');
      });

    socket.on('newMessage', async function (messageData) {
      console.log('-------------------------New Message----------------------', String(messageData));
      //TODO Save Message in Database

      try {
        socket.broadcast.to(socket.projectId).emit('newMessage', messageData);
        console.log('\n\n\n\n\n broadcast sent\n\n' + JSON.stringify(messageData) + '\n\n\n');
      } catch (error) {
        console.log('\n\n\n\n\n broadcast error\n\n\n\n\n');
        console.log(String(error));

        console.log(error);
        //TODO Handle Message Sending Error
      }
    });

  });
}

Is this any issue with the browser or something else that i need to ask from stack-overflow community?

@nathanheffley
Copy link

@manjotsk I'm not sure if you've fixed it by now, but on your server side code you are listening for disconnectt(notice the double t) but your front-end is emitting disconnect. Also, you probably don't want to emit disconnect as that event is supposed to be sent from client to server when the client disconnects.

@kognise
Copy link

kognise commented Mar 23, 2019

I have code that relies on the socket emitting the disconnect event to prevent duplicate ips-- users who reload my app quickly get blocked because the disconnect even never fires!

@manjotsk
Copy link

@manjotsk I'm not sure if you've fixed it by now, but on your server side code you are listening for disconnectt(notice the double t) but your front-end is emitting disconnect. Also, you probably don't want to emit disconnect as that event is supposed to be sent from client to server when the client disconnects.
disconnectt was an impostor alias that I was using! Thank you for pointing out. I'll recheck with this on both sides. And, obviously, the implementation was wrong! I got a clearer view! Thank you @nathanheffley 👍 :)

@kognise
Copy link

kognise commented Mar 24, 2019

@manjotsk What?

@alvarojrio
Copy link

and only use socket.once instead socket.on
"customer level."
exemple:
socket.on('connect')
use
socket.once('connect'
.

@Xcode09
Copy link

Xcode09 commented Jul 29, 2019

same here my
socket.on("message") { (dataArray, socketAck) -> Void in

  if let data = dataArray.first as? Data{
    do{
      let objc = try JSONDecoder.init().decode(GetChatConversation.self, from: data)
      completionHandler(objc,nil)
    }
    catch let error{
      return completionHandler(nil,error.localizedDescription)
    }
  }else{
    completionHandler(nil,"Cannot cast Array of Any to Data")
  }
}

do not return the callback if anyone one knows tell me

@Ehsan666x
Copy link

are you dumb? you are waiting for an emit on client but no emit on server. fuck out of here

@ghost
Copy link

ghost commented Sep 1, 2019

That's some real negative energy, Ehsan666x.

@Hassuunna
Copy link

I handled this problem this way. I've made an emit sender on client which is calling heartbeat on server.
hbeat[socket.id] = Date.now();

I wonder what hbeat value should be sent from client-side?

@Nicekor
Copy link

Nicekor commented Oct 12, 2020

Instead of socket.disconnect() or socket.emit('disconnect') try socket.close(); in the client side and it should trigger the 'disconnect' event on the server side. It worked for me.

@darrachequesne
Copy link
Member

Closed as unable to reproduce, please reopen if needed.

@kognise
Copy link

kognise commented Jan 14, 2023

hahaha wow i can't believe i was on this thread 4 years ago

@nandobfer
Copy link

@nathanheffley @kognise HAHAHA! I was dumb when I was learning this as a noob intern. Coming back as a CTO on this thread, after 5 years, now makes me feel dumber, but what a journey! lol!

what was the solution? io.close() is an alias for io.disconnect() and didn't work

@darrachequesne
Copy link
Member

@nandobfer could you please open a new issue with all necessary details? Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
unable to reproduce We were unable to reproduce the issue
Projects
None yet
Development

No branches or pull requests