解决 Socket.io 连接时客户端 socket.id 变化问题

引言

在 Web 开发过程中,我们常常需要使用 Socket.io 来进行实时通信。Socket.io 可以轻松实现基于 WebSocket 的双向通信,其中较为常用的特性之一就是使用 socket.id 来唯一标识客户端。然而,在一些特定的情况下,我们会发现客户端 socket.id 会在重连时发生变化,造成问题。

本文就介绍一下为什么客户端 socket.id 会发生变化,以及如何解决这一问题。

问题背景

在使用 Socket.io 的过程中,我们会发现客户端的 socket.id 并不是固定不变的,而是会随着客户端与服务器的连接情况而变化。

具体来说,当客户端与服务器第一次建立连接时,Socket.io 会在客户端上生成一个唯一的 socket.id。此后,如果客户端与服务器间的连接中断,然后重新连接,Socket.io 会在客户端上再次生成一个 socket.id。这个新的 socket.id 就和之前的 socket.id 不同了。

这样的话,当我们在客户端上维护一些本地状态时,就需要额外的逻辑来重新绑定状态和新的 socket.id

问题原因

问题的原理在 Socket.io 官方文档中有所说明。[1]

实际上,客户端 socket.id 发生变化的情况路由到了底层的 WebSocket 实现。在某些特定的网络条件下,WebSocket 连接可能会随时中断,例如断网、从一个 WiFi 热点切换到另一个热点、移动设备在网络上漫游等。在这些网络中断的情况下,WebSocket 客户端需要在后台进行一系列的重新连接尝试,以保持与服务器的稳定连接。这些重新连接的过程可能会使用新的 WebSocket 连接,从而导致客户端 socket.id 的变化。

解决方法

要解决客户端 socket.id 发生变化的问题,通常有以下两种方式。

方式一:使用 userId 等稳定标识

一种解决方法就是在客户端本地维护一个稳定的用户唯一标识(例如 userId),然后将这个唯一标识与 socket.id 建立映射关系,这样无论 socket.id 是否发生变化,我们都可以通过这个稳定的唯一标识来操作本地状态。例如:

-- ---
----- ------ - ------------

-------------------- -- -- -
  -------------------- --------
---

----------------------- -- -- -
  -- ---
---

-- ---
------------------- ------ -- -
  ------------------ ------ -- -
    --------------------
    ------------- - -------
  ---

  ----------------------- -- -- -
    ----- ------ - --------------
    -- -------- -
      ---------------------
    -
  ---
---

方式二:使用 io.sockets.sockets 获取所有的 socket

另一种解决方法是使用 io.sockets.sockets 来获取所有的 socket,然后根据客户端的 IP 地址等信息进行匹配来重新绑定本地状态。

例如可以使用如下代码来获取所有连接的 socket

----- ------- - -------------------

然后可以使用如下代码来根据客户端的 IP 地址等信息进行匹配:

----- ------ - ----------------------------- -- -
  ------ ------------------- --- ----------------
---

-- -------- -
  -- ---
-

总结

客户端 socket.id 的变化是 Socket.io 的一个特殊情况,需要我们在编写代码时特别考虑,以免出现问题。

本文介绍了客户端 socket.id 发生变化的原因,以及如何通过维护稳定的唯一标识或者使用 io.sockets.sockets 获取所有的 socket 来解决这一问题。了解了这些解决方法后,我们就可以更加自如地使用 Socket.io 进行实时通信,并且避免客户端 socket.id 发生变化造成的问题。

参考链接

  1. https://socket.io/docs/v3/websocket-transport/#The-differences-between-a-Socket.io-socket-and-the-built-in-WebSocket-object

来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/664beeded3423812e4ac6f3b