从浏览器发送 websocket ping/pong 帧

IT技术 javascript websocket mongrel2
2021-01-31 15:03:31

我一直在阅读有关 websockets 中的 ping/pong 消息以保持连接有效,但我不确定它们是什么。它是一种独特的框架类型吗?(我在 chrome 中的 javascript WebSocket 对象上没有看到与乒乓相关的任何方法)。或者它只是一种设计模式(例如,我从字面上向服务器发送“ping”或任何其他字符串并让它响应)。乒乓球与连续帧有关吗?

我问的原因是我使用的是在 Mongrel2 后面运行的 python 框架,所以我想知道是否有办法向 Mongrel2 发送特定的 ping/pong 消息,告诉它保持连接活动,而我的 python 应用程序不需要担心它。我想类似于为它提供一个单独的 HTTP 方法。我想一个专用的 ping/pong 消息帧可能比字符串“ping”更简单(服务器和网络上的负载更少),尽管这可能不会太重要。

编辑:我刚刚查看了RFC 6455,看起来 Ping 和 Pong 绝对是具有自己操作码的控制帧类型。那么如何在 Chrome 中从 javascript 发送 Ping 帧呢?

3个回答

没有用于发送 ping 帧或接收 pong 帧的 Javascript API。这要么受您的浏览器支持,要么不受支持。也没有用于启用、配置或检测浏览器是否支持和正在使用乒乓帧的 API。有关于为此创建 Javascript ping/pong API 的讨论将来有可能 ping 是可配置/可检测的,但 Javascript 不太可能直接发送和接收 ping/pong 帧。

但是,如果您同时控制客户端和服务器代码,则可以轻松地在更高级别添加 ping/pong 支持。如果您还没有,您的消息中将需要某种消息类型标头/元数据,但这很简单。除非您计划每秒发送数百次 ping 或同时拥有数千个客户端,否则您自己完成的开销将非常小。

@bigmugcup 链接失效了
2021-04-14 15:03:31

Ping 只能从服务器发送到客户端,浏览器应尽快自动回复 Pong OpCode。因此,您不必担心更高级别的问题。

尽管并非所有浏览器都像他们想象的那样支持标准,但它们在实现这种机制方面可能存在一些差异,甚至可能意味着没有 Pong 响应功能。但就我个人而言,我使用的是 Ping/Pong,从未见过没有在低级客户端实现上实现这种类型的 OpCode 和自动响应的客户端。

如果您希望客户端自动检测断开状态(当没有收到 RST/FIN 数据包,但网络已断开),那么您还需要让客户端发起 ping 数据包。
2021-03-18 15:03:31
你在哪里读到 ping 只是从服务器到客户端?RFC 说“端点可以在建立连接后和关闭连接之前的任何时间发送 Ping 帧。”
2021-03-24 15:03:31
当用户代理频繁刷新时,仅服务器 ping 可能是推荐的做法。但是现在许多网站都被设计为 SPA。在这种环境中,客户端应用程序定期 ping 服务器以确保连接没有丢失可能非常重要。
2021-03-25 15:03:31
当未收到 RST/FIN 数据包时,TCP 不会通知断开连接。TCP 仅在发送方尝试在断开的连接上发送时检测断开的连接。Ping 在许多应用程序中用作心跳,这是一种有效的用途。死连接将永远保持死状态,直到客户端尝试发送。因此,对于浏览器上的 WebSockets,必须使用自定义 ping(或心跳)消息来检测客户端的客户端断开连接。服务器可能正在尝试 ping,并检测到客户端断开连接,但未通知客户端。客户端 ping 也很好。
2021-04-07 15:03:31
在 RFC 6455,WebSocket 协议中,它明确指出:“注意:Ping 帧可以用作保持连接或作为验证远程端点仍然响应的手段。”
2021-04-09 15:03:31

js中的一个可能的解决方案

如果 WebSocket 服务器主动ws在几分钟后断开链接,则服务器和客户端之间没有消息发送。

  1. 客户端主动发送自定义ping消息,使用该keepAlive函数保持活动状态

  2. 服务器端会忽略自定义ping消息并响应自定义pong消息

let timerId = 0; 

function keepAlive(timeout = 20000) { 
    if (webSocket.readyState == webSocket.OPEN) {  
        webSocket.send('');  
    }  
    timerId = setTimeout(keepAlive, timeout);  
}

function cancelKeepAlive() {  
    if (timerId) {  
        clearTimeout(timerId);  
    }  
}

这让我了解了一个保持活动的功能,在我的情况下,它通知服务器更新 websocket 连接上的读取截止日期值(顺便说一句,我在 golang 服务器中)。虽然我必须通过模拟它来发送乒乓球来让它更有意义。谢谢!来自坦桑尼亚。
2021-04-02 15:03:31
此代码发送空帧,而不是 ping 或 pong 帧。
2021-04-05 15:03:31
@RememberMonica 请先阅读我的描述,我知道发生了什么。
2021-04-10 15:03:31