socket.io断线后重连和消息离线存储如何实现
发布于 8 年前 作者 M6ZeroG 13998 次浏览 来自 问答

刚刚了解了一下socket.io,想使用socket.io来做即时通讯server,但是由于不了解socket.io发现: 关于断线后重连

  1. 如何去区别对待客户端是暂时断开连接(因为网络不稳定或者其他问题),还是永久的断开连接;
  2. 如果是暂时断开连接,通过什么方式能使客户端重新连接到服务器时,重连后服务器使用的那个与client通讯的socket能重用断开连接前的socket;
  3. 如果在网络不稳定情况下多次断开重连,重连时服务器端不去重用socket,考虑这种情况: 在断开连接前该socket加入了很多房间,重连后由于没有重用原来的socket,需要重新认证客户端并把新的socket重新一个个的join到这些房间,这样会不会很没有效率

关于消息离线存储

  1. 向room中发送消息,那些处于永久断线的用户逻辑上虽然加入了该room,但是由于离线所以无法将该消息推送到这些客户端(room 中没有对应的socket),怎么做这些用户的消息离线存储? 因为单聊情况下可以通过这种方式做离线存储: 通过对方的userId找到对方的当前socketId(假设userId,socketId映射关系在某处可以查得,并且会实时更新),以此获取对方的socket实例然后向该socket连接的客户端推送消息,这样如果未找到userId,socketId映射关系说明该用户处于永久断开的状态,可以在Redis中存储离线的消息,等对方连接后再推送。但是向socket.io的room中群发消息,不清楚如何做消息离线存储.
2 回复

1、socket.io的默认机制是,每25秒客户端发送一次ping,服务端回复一次pong,60秒内没收到ping,就说明断开了,把connected字段设为false 所以说,60秒内没有响应,就认为永久断开了 客户端主动断开前,会发送一个断开消息,服务端收到这个消息后立即断开 2、断开后,原来的socket就没有用了,需要重新连 join操作只是把room加入到rooms字段(如果用了socket.io-redis,还会发送一条redis订阅命令),并不需要很多资源 3、socket.io的room机制类似于标签,rooms字段里默认就有socket.id的room,所以也可以通过to(socket.id).emit()来向某个socket发送消息,对于某个用户,可以加入类似"user-" + userId的room,向这个room发送消息,这个用户就会收到这个消息了 对于需要可靠聊天的需求,连接后,需要服务端主动推送未收到的聊天,所有聊天都要保存起来,客户端收到后,发送收到的聊天已被接收的消息,数据库再相应修改下状态 其实和socket.io无关了,实现和普通的消息/站内信已读/未读类似

@plantain-00 很详细,谢谢

回到顶部