WebSockets 可以选择将ping发送到另一端,另一端应该用pong响应.
收到Ping帧后,端点必须发送Pong帧作为响应,除非它已经收到一个关闭帧.它应该尽快响应Pong框架.
[Y]你向对等体发送一个keepalive探测包,其中没有数据,并且ACK标志打开.您可以这样做是因为TCP/IP规范,作为一种重复的ACK,并且远程端点将没有参数,因为TCP是面向流的协议.另一方面,您将收到来自远程主机的回复(根本不需要支持keepalive,只需TCP/IP),没有数据和ACK设置.
我认为TCP keepalive效率更高,因为它可以在内核中处理而无需将数据传输到用户空间,解析websocket框架,制作响应框架,然后将其交回内核进行传输.它也减少了网络流量.
此外,WebSockets 被明确指定为始终在TCP上运行; 它们不是传输层不可知的,因此TCP keepalive始终可用:
WebSocket协议是一种独立的基于TCP的协议.
那么为什么人们会想要使用WebSocket ping/pong而不是TCP keepalive?
我有一个webapp,它在浏览器中运行.该webapp连接到使用websockets的服务器.所以服务器和我的客户端/浏览器之间的通信基于websockets.如果服务器上发生了一些魔术事件,某些Web服务会向我的webapp发送一个新的XML/JSON,并显示新数据.
但是,作为客户端/浏览器,我如何知道连接是否仍处于活动状态?假设我在大约30秒内没有获得任何新的XML.我怎么知道连接是否关闭/中断/服务器离线或一切正常,但在服务器本身没有发生新的魔术事件.
对于 Apollo 订阅的 keepAlive 有一些麻烦。每当我将时间设置为秒或更长时间时,监听订阅就会出错。
{
"error": "Could not connect to websocket endpoint ws://website.test:8000/graphql. Please check if the endpoint url is correct."
}
Run Code Online (Sandbox Code Playgroud)
这是 ApolloServer 设置
const apollo = new ApolloServer({
introspection: true,
playground: true,
typeDefs: schema,
subscriptions: {
keepAlive: 40000,
},
resolvers,
context: ........
}
Run Code Online (Sandbox Code Playgroud)
在我的本地环境中,当我没有设置 keepAlive 时,它将无限期地保持打开状态。如果我将它设置为 10000 效果很好。保持活动设置为 40000 我收到错误并且连接关闭
更新我们刚刚注意到的一件事是这个问题发生在操场上,而不是我们的网络应用程序上。也许只是一个游乐场?