Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to reconnect socket after a passive network switch

So I have a Swift client, Node.js server, and am using socket.io. I have an issue where when the user changes from WiFi to LTE (passively, if they turn off wifi manually it works fine) while being connected to the server, for some reason they don't reconnect to the server (just hit a ping timeout). I've tried increasing ping timeout to 50 seconds with no effect. My users interact with each other while being connected to the same room so this is a big issue.

My connection code on the client-side looks like this:

var socket: SocketIOClient?
fileprivate var manager: SocketManager?

func establishConnection(_ completion: (() -> Void)? = nil) {
    let socketUrlString: String = serverURL
    self.manager = SocketManager(socketURL: URL(string: socketUrlString)!, config: [.forceWebsockets(true), .log(false), .reconnects(true), .extraHeaders(["id": myDatabaseID])])
    self.socket = manager?.defaultSocket
    self.socket?.connect()
        //self.socket?.on events go here
}

On the client side, my connection code looks like:

const io = require('socket.io')(http, {
  pingTimeout: 10000
});

io.on('connection', onConnection);

function onConnection(socket){
  let headerDatabaseID = socket.handshake.headers.id
  //in the for loop below, I essentially disconnect any socket that has the same database ID as the one that just connected (in this case, when a client is in a room with other clients, 
  //and then he/she switches from WiFi to LTE, the client reconnects to the socket server and this removes the old connection from the room it was in)
  for (let [id, connectedSocket] of io.sockets.sockets) {
    if (connectedSocket.databaseID == headerDatabaseID && socket.id != id) {
      connectedSocket.disconnect()
      break
    }
  }
//socket.on() events here
}

My issue is this--how do I go about reconnecting the client when it makes the passive network switch (WiFi -> LTE or vice versa)? I thought that just adding .reconnects(true) would work but for some reason, it's not...

Please let me know if I can be more detailed/helpful or if you'd like to see other codes.

like image 474
nickcoding2 Avatar asked Nov 01 '21 12:11

nickcoding2


People also ask

How to reconnect to WebSocket after close connection with HTML?

How to reconnect to websocket after close connection with HTML? Recreate the socket to reconnect it. The websockets are designed to stay open. You can also go with the method to have the server close the connection. Through this, the websocket will fire an onclose event and would amazingly continue attempting to make the connection.

What happens when a socket loses a connection?

When the listening socket accepts a connection, it returns a new socket that represents that connection. When you detect a loss of connection, close the corresponding connection socket but leave the listening socket running. On a side note, IMO the best way to detect a loss of connection is to periodically send data (in both directions).

Why can't I reconnect to the server when the client loses Internet?

It needs to check if the client is connected (from the server side) and vice-versa for the client. When the client loses internet, the server needs to know it is disconnected. Then, the client needs to reconnect to the server when it regains internet When the client loses internet and then regains internet, I can't reconnect using the same port.

Should I bind the client socket to the port?

Don't bind the client socket. Only the server port is important. On the server side, just keep the listening socket listening. When the listening socket accepts a connection, it returns a new socket that represents that connection.


Video Answer


2 Answers

I believe the solution to you problem can be either simple or complex; that depends on your requirements. I assume that each chat room has its own ID.

If you store that ID in memory on the device, when the user reconnects, you can have the socket reconnect to the room ID you had last and they will re-join that room. This is insecure.

If rooms are protected and not public, someone may be able to connect to a room that they are not allowed in if they know/can guess the room ID. To solve that problem, you'd need to implement some sort of authentication or server side database that keep keep track of that sort of stuff.

like image 83
Zero Avatar answered Nov 15 '22 17:11

Zero


Considering the behavior varies based on whether the handoff is manual or passive it sounds like the issue is on the iOS client. I notice that you are using sockets - it seems to be some sort of custom sockets package, right? Is there a reason for using this? URLSession is a higher level implementation and it manages things like handoff.

There is something called Wifi assist, developed by apple, to manage handoff. It is part of the OS and manages this internally. According to apple: "Using URLSession and the Network framework already gives us the new WiFi assist benefits.". This was released in iOS 9, in Sept 2015. But if you are using some other kind of sockets, whatever this "socketIOClient" is - especially packages developed prior to Sept 2015, you are probably bypassing Wifi assist. The latest version of SocketIO client I see was written in 2015 and it appears support for this package was discontinued when iOS 9 came out.

When the user manually changes the connection this is manually prompting the OS to tear down & reestablish the connection, whereas with passive tradeoff it normally relies on this Wifi Assist.

You could try to programmatically tear down & reestablish the connection when you detect that a passive handoff has occurred, but I wouldn't recommend this... for starters, it will make your code much messier. It will probably degrade the user experience. But worse, this may not be the only problem you run into using this outdated socketIO package. There's really no telling what kind of maintenance problems you will wind up with. Better to just refactor your code to use the up to date networking mechanisms provided by iOS.

like image 29
ibrust Avatar answered Nov 15 '22 16:11

ibrust