Así que tengo un cliente Swift, un servidor Node.js y estoy usando socket.io. Tengo un problema en el que cuando el usuario cambia de WiFi a LTE (pasivamente, si apaga el wifi manualmente, funciona bien) mientras está conectado al servidor, por alguna razón no se vuelve a conectar al servidor (simplemente presiona un tiempo de espera de ping ). Intenté aumentar el tiempo de espera del ping a 50 segundos sin ningún efecto. Mis usuarios interactúan entre sí mientras están conectados a la misma sala, por lo que este es un gran problema.
Mi código de conexión en el lado del cliente se ve así:
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 }En el lado del cliente, mi código de conexión se ve así:
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 }Mi problema es este: ¿cómo hago para volver a conectar al cliente cuando hace el cambio de red pasiva (WiFi -> LTE o viceversa)? Pensé que simplemente agregar .reconnects(true) funcionaría, pero por alguna razón, no es así...
Avíseme si puedo ser más detallado/útil o si desea ver otros códigos.
Creo que la solución a su problema puede ser simple o compleja; eso depende de sus requisitos. Supongo que cada sala de chat tiene su propia identificación.
Si almacena esa identificación en la memoria del dispositivo, cuando el usuario se vuelva a conectar, puede hacer que el socket se vuelva a conectar a la última identificación de la habitación que tenía y se volverán a unir a esa habitación. Esto es inseguro.
Si las salas están protegidas y no son públicas, es posible que alguien pueda conectarse a una sala en la que no está permitido si sabe o puede adivinar la identificación de la sala. Para resolver ese problema, necesitaría implementar algún tipo de autenticación o base de datos del lado del servidor que realice un seguimiento de ese tipo de cosas.
Teniendo en cuenta que el comportamiento varía en función de si la transferencia es manual o pasiva, parece que el problema está en el cliente de iOS. Me doy cuenta de que está utilizando sockets; parece ser algún tipo de paquete de sockets personalizado, ¿verdad? ¿Hay alguna razón para usar esto? URLSession es una implementación de nivel superior y administra cosas como el traspaso.
Hay algo llamado asistencia Wifi, desarrollado por Apple, para administrar la transferencia. Es parte del sistema operativo y lo administra internamente. Según Apple: "Usar URLSession y el marco de red ya nos brinda los nuevos beneficios de asistencia WiFi". Esto se lanzó en iOS 9, en septiembre de 2015. Pero si está utilizando algún otro tipo de socket, sea lo que sea este "socketIOClient", especialmente los paquetes desarrollados antes de septiembre de 2015, probablemente esté pasando por alto la asistencia de Wifi. La última versión del cliente SocketIO que veo se escribió en 2015 y parece que el soporte para este paquete se suspendió cuando salió iOS 9.
Cuando el usuario cambia manualmente la conexión, esto está solicitando manualmente al sistema operativo que desconecte y restablezca la conexión, mientras que con el intercambio pasivo normalmente se basa en esta asistencia Wifi.
Podría intentar desmantelar y restablecer la conexión mediante programación cuando detecte que se ha producido una transferencia pasiva, pero no recomendaría esto... para empezar, hará que su código sea mucho más complicado. Probablemente degradará la experiencia del usuario. Pero lo que es peor, es posible que este no sea el único problema con el que se encuentre al usar este paquete obsoleto de socketIO. Realmente no se sabe con qué tipo de problemas de mantenimiento terminará. Es mejor simplemente refactorizar su código para usar los mecanismos de red actualizados proporcionados por iOS.
Si .reconnects(true) no funciona, puede intentar solucionar el problema manualmente con la accesibilidad de Apple. Esto puede hacerlo más fácil: es la funcionalidad de Accesibilidad "reescrita en Swift con cierres".
En tu caso, podrías usarlo como tal:
let reachability = try! Reachability() reachability.whenReachable = { reachability in if reachability.connection == .wifi { print("Reachable via WiFi") self.socket.disconnect(); establishConnection() //this is your method defined in the question } else { print("Reachable via Cellular") self.socket.disconnect(); establishConnection() //this is your method defined in the question } } reachability.whenUnreachable = { _ in print("Not reachable") } do { try reachability.startNotifier() } catch { print("Unable to start notifier") }