非活动客户端连接的socket.io服务器端超时?

Posted

技术标签:

【中文标题】非活动客户端连接的socket.io服务器端超时?【英文标题】:socket.io server-side timeout for inactive client connection? 【发布时间】:2015-09-08 13:49:30 【问题描述】:

我知道,如果 socket.io 客户端库没有定期收到对其发送到服务器的 ping 数据包的响应(假设由于某种原因,连接已断开)。而且,还有用于控制这种重新连接行为的客户端选项。

但是,如果客户端不活动并停止发送 ping 消息(比如因为客户端进入睡眠状态),服务器端会发生什么?我在 socket.io 服务器端文档中找不到任何解释这种情况或允许对其进行配置的信息。服务器会关闭一个不活动的客户端 socket.io 连接(它没有从它接收 ping 消息的连接)吗?如果是这样,服务器将等待多长时间?该行为是否可配置?

【问题讨论】:

如果您在 socket.io 文档中找不到合适的内容,您可以为此行为编写自己的代码。 重新。服务器端,socket.on('disconnect', ...) 会在超时后处理任何客户端无响应吗? disconnect 捕获离开页面的客户,您可以使用io.engine.clientsCount 显示剩余的客户。 @Data - 仅当客户端以有序的方式关闭并关闭其套接字时才会发生断开连接,而不是仅在它们失去连接时才会发生。当客户端刚刚失去连接时,此时不会向服务器发送任何内容。服务器必须以某种方式意识到,嗯,我已经很久没有收到这个客户端的任何消息了——我想知道他们现在是否已经消失了。 socket.io 协议的 ping/pong 部分是为了帮助检测这种情况。 这个有帮助吗:“非活动,io 会自动关闭一个套接字”,***.com/a/9708962/1837472 【参考方案1】:

根据 socket.io 2.20 自述文件(截至 2020 年 1 月的最新版本):

“在 Engine.IO 级别实现了心跳机制,允许服务器和客户端都知道对方何时不再响应。

该功能是通过在服务器和客户端上设置的计时器实现的,并在连接握手期间共享超时值(pingIntervalpingTimeout 参数)。"

因此,您可以通过在 socket.io 内的 engine.io 组件上设置以下超时属性来配置服务器端和客户端超时设置。

使用 socket.io 2.20 版:

const io = ...; // initialize socket.io how you wish
io.eio.pingTimeout = 120000; // 2 minutes
io.eio.pingInterval = 5000;  // 5 seconds

使用旧版本的 socket.io 也是如此:

const io = ...; // initialize socket.io how you wish
io.set('heartbeat timeout', 1200000);
io.set('heartbeat interval', 5000);

【讨论】:

【参考方案2】:

Disconnection detection

Engine.IO 连接在以下情况下被视为关闭:

一个 HTTP 请求(GET 或 POST)失败(例如,当服务器关闭时) WebSocket 连接已关闭(例如,当用户关闭其浏览器中的选项卡时) socket.disconnect() 在服务器端或客户端调用 还有一种心跳机制检查服务器和客户端之间的连接是否仍然正常运行:

在给定的时间间隔(握手中发送的 pingInterval 值),服务器发送一个 PING 数据包,客户端有几秒钟(pingTimeout 值)发送一个 PONG 数据包。如果服务器没有收到返回的 PONG 数据包,则认为连接已关闭。反之,如果客户端在 pingInterval + pingTimeout 内没有收到 PING 包,则认为连接已关闭。

断开连接的原因列在here(服务器端)和here(客户端)。

pingTimeout(Number): 没有pong包多少毫秒认为连接关闭(60000)

pingInterval(Number):多少毫秒再发送一个新的ping包(25000)

https://socket.io/docs/v4/server-api/

https://github.com/socketio/engine.io#methods-1

【讨论】:

这两个不是客户端设置吗? 我不这么认为。查看答案中的链接 我在您链接的 server-api 页面上看不到这些设置。 问题在于发送 ping 的是客户端,而服务器则使用 pong 进行响应。因此,这两个设置都控制客户端的行为,即发送 ping 的频率以及等待 pong 响应的时间。在我看来,它们似乎并不真正适用于服务器。我想知道服务器在一段时间内没有 ping 时会做什么。服务器不会按时间间隔发送 ping。它只是监听 ping 并发送一个 pong 作为响应。 当客户端连接时,服务器做的第一件事就是发送一个打开事件socket received: type 'open', data '"sid":"zc8mQaGAEYuC_FTKAAA8","upgrades":["websocket"],"pingInterval":25000,"pingTimeout":60000',并带有所需的时间间隔和超时。然后客户端在打乒乓球时遵守这些规则。【参考方案3】:

在 socket.io 2.20 上。这可以在初始化socket.io时设置

const io = require("socket.io")(pingTimeout: 10000, pingInterval: 30000);

查看所有选项及其默认值here

【讨论】:

以上是关于非活动客户端连接的socket.io服务器端超时?的主要内容,如果未能解决你的问题,请参考以下文章

在 socket.io 中控制来自客户端的心跳超时

Socket.io 与 flask-socketio python。如何设置套接字保持活动/超时

Socket.io - nodejs 服务器端。重新连接后传输关闭

socket.io 中的连接限制

客户端和服务器端(React/Node.js)之间的 Socket.io 连接失败

在 socket.io 上设置高关闭超时是不是安全?