【问题标题】:Sending websocket ping/pong frame from browser从浏览器发送 websocket ping/pong 帧
【发布时间】:2012-05-22 01:21:58
【问题描述】:

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

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

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

【问题讨论】:

  • 只是从服务器ping。每个人都知道非标准端口上的网络问题,所以他们开始定期 ping。我想你可以 ping 一个写得不好的服务器,但对它们做任何敏感的事情可能不太聪明。
  • @user1382306 来自服务器的 ping 将非常快地使用移动设备电池。从客户端 ping 可以节省设备电池。
  • @user1382306 不是每个人!非标准端口的网络问题是什么?

标签: javascript websocket mongrel2


【解决方案1】:

没有用于发送 ping 帧或接收 pong 帧的 Javascript API。您的浏览器要么支持,要么不支持。也没有 API 可以启用、配置或检测浏览器是否支持和使用 ping/pong 帧。为此有discussion about creating a Javascript ping/pong API。将来 ping 有可能是可配置/可检测的,但 Javascript 不太可能直接发送和接收 ping/pong 帧。

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

【讨论】:

  • @bigmugcup 链接失效
【解决方案2】:

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

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

【讨论】:

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

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);  
    }  
}

【讨论】:

  • 此代码发送空帧,而不是 ping 或 pong 帧。
  • @RememberMonica 请先阅读我的描述,我知道发生了什么。
  • 这让我了解了一个保持活动状态的功能,在我的情况下,它通知服务器更新 websocket 连接上的读取截止日期值(顺便说一句,我在 golang 服务器中)。尽管我必须通过模拟它来发送乒乓球串来使其更有意义。谢谢!来自坦桑尼亚。
猜你喜欢
  • 1970-01-01
  • 2019-03-16
  • 2020-12-29
  • 2018-02-08
  • 1970-01-01
  • 2016-05-13
  • 2017-04-30
  • 1970-01-01
  • 2018-08-11
相关资源
最近更新 更多