从浏览器发送WebSocket ping/pong帧

i5desfxk  于 2023-04-21  发布在  其他
关注(0)|答案(4)|浏览(524)

我一直在阅读关于在websockets中使用ping/pong消息来保持连接的文章但我不确定它们是什么。是一种独特的帧类型吗?(我在chrome中的javascript WebSocket对象上没有看到任何与ping-pong相关的方法)。(例如,我按字面意思发送“ping”或任何其他字符串到服务器,并让它响应)乒乓是否与连续帧有关?
我问这个问题的原因是我使用的是一个运行在Mongrel 2后面的Python框架,所以我想知道是否有一种方法可以向Mongrel 2发送一个特定的ping/pong消息,告诉它保持连接,而不需要我的Python应用程序担心它。类似于为它提供一个单独的HTTP方法,我想是的。我想一个专用的ping/pong消息帧可能比字符串“ping”更简单(服务器和网络上的负载更少),尽管这可能不会有太大的影响。
编辑:我刚刚看了RFC 6455,看起来Ping和Pong肯定是有自己操作码的控制帧类型。那么我如何在Chrome中从javascript发送Ping帧呢?

hof1towb

hof1towb1#

没有Javascript API来发送ping帧或接收pong帧。您的浏览器是否支持这一点。也没有API来启用,配置或检测浏览器是否支持和使用ping/pong帧。有discussion about creating a Javascript ping/pong API用于此。将来可能会配置/检测ping,但是Javascript不太可能能够直接发送和接收ping/pong帧。
但是,如果你同时控制客户端和服务器端的代码,那么你可以很容易地在更高的级别上添加ping/pong支持。如果你还没有消息类型头/元数据,你需要在消息中添加一些消息类型头/元数据,但这很简单。除非你打算每秒发送数百次ping,或者有数千个客户端同时发送ping,否则你自己做的开销会很小。

eit6fx6z

eit6fx6z2#

**更新:**虽然答案是旧的,但它在google的热门结果中,在握手后的任何时候,客户端或服务器都可以选择向对方发送ping

Ping只从服务器发送到客户端,浏览器应该尽快使用Pong OpCode自动应答。因此您不必担心更高级别的问题。
虽然不是所有的浏览器都支持标准的,因为他们假设,他们可能会有一些差异,在实现这种机制,甚至可能意味着没有Pong响应功能。但我个人使用Ping / Pong,从来没有见过客户端不实现这种类型的OpCode和自动响应在低级别的客户端实现。

cwdobuhd

cwdobuhd3#

一个可能的js解决方案

在WebSocket服务器主动断开ws链接的情况下,几分钟后服务器和客户端之间没有发送任何消息。
1.客户端主动发送自定义ping消息,以通过使用keepAlive函数保持活动
1.服务器端将忽略自定义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);  
    }  
}
oxcyiej7

oxcyiej74#

不知道
我尝试实现ping。似乎没有任何方法可以强制浏览器WebSocket客户端设置0x1(字符串)和0x2(二进制)以外的任何操作码。

const socket = new WebSocket(url);
ping() {
    if (socket?.readyState !== WebSocket.OPEN) {
      return;
    }
    const buffer = new ArrayBuffer(7);
    const dataView = new DataView(buffer);
    dataView.setInt8(0, 0x89);
    dataView.setInt8(1, 0x00);
    dataView.setInt8(2, 0x48);
    dataView.setInt8(3, 0x65);
    dataView.setInt8(4, 0x6c);
    dataView.setInt8(5, 0x6c);
    dataView.setInt8(6, 0x6f);
    socket.send(buffer);
  }
socket.addEventListener('open', ping);

这段代码应该发送一个最终的(0x8)ping帧(操作码0x09),其主体为“hello”,但浏览器发送的最终帧是二进制(0x82),其主体为“hello”,其中“hello”是0x89数据。

相关问题