简体   繁体   English

如何在javascript中实现对webSocket连接的Ping / Pong请求?

[英]How to implement Ping/Pong request for webSocket connection alive in javascript?

I use websocket in javascript. 我在javascript中使用websocket。 But the connection close after one minute. 但一分钟后连接关闭。

I am wondering somethings: 我想知道一些事情:

1- Is not Websocket naturaly providing with Ping/Pong messages not to close the connection? 1- Websocket是否自然提供Ping / Pong消息而不关闭连接? I think it have to. 我认为必须这样做。 Otherwise what is the difference between websocket and TCP connection? 否则websocket和TCP连接有什么区别?

2- If I have to send the ping/pong messages, how is the ping message sent? 2-如果我必须发送ping / pong消息,ping消息是如何发送的? What am I need to do? 我需要做什么? Is WebSocket object provide a ping method? WebSocket对象是否提供ping方法? Or should I call a method as websocket.send("ping") ? 或者我应该将方法称为websocket.send(“ping”)? I am use naturaly WebSocket object in javascipt. 我在javascipt中使用naturaly WebSocket对象。

3- Should the server respond to Ping requests with Pong? 3-服务器是否应该使用Pong响应Ping请求? Should this be implemented separately on the server side? 这应该在服务器端单独实现吗?

Note:Sorry for my english. 注意:抱歉我的英文。

Yes, there are ping/pong frames in websockets. 是的,websockets中有ping / pong框架。 Here is an example using the ws module, where the server is initiating the ping request: 以下是使用ws模块的示例,其中服务器正在启动ping请求:

const http = require('http');
const ws = require('ws');

const server = http.createServer(function(req_stream_in, res_stream_out) {
  // handle regular HTTP requests here
});
const webSocketServer = new ws.Server({
  path: "/websocket",
  server: server
});

const connected_clients = new Map();

webSocketServer.on('connection', function connection(ws_client_stream) {
  // NOTE: only for demonstration, will cause collisions.  Use a UUID or some other identifier that's actually unique.
  const this_stream_id = Array.from(connected_clients.values()).length;

  // Keep track of the stream, so that we can send all of them messages.
  connected_clients.set(this_stream_id, ws_client_stream);

  // Attach event handler to mark this client as alive when pinged.
  ws_client_stream.is_alive = true;
  ws_client_stream.on('pong', () => { ws_client_stream.is_alive = true; });

  // When the stream is closed, clean up the stream reference.
  ws_client_stream.on('close', function() {
    connected_clients.delete(this_stream_id);
  });
});

setInterval(function ping() {
  Array.from(connected_clients.values()).forEach(function each(client_stream) {
    if (!client_stream.is_alive) { client_stream.terminate(); return; }
    client_stream.is_alive = false;
    client_stream.ping();
  });
}, 1000);

At this point in time, heartbeats are normally implemented on the server side: there's not much you can do from the client end. 此时,心跳通常在服务器端实现:您无法从客户端执行任何操作。

However, if the server keeps killing your socket connection, and you have no control over it, it is possible for the client to send arbitrary data to the websocket on an interval: 但是,如果服务器继续终止套接字连接,并且您无法控制它,则客户端可能会在一定时间间隔内向websocket发送任意数据:

let socket = null;

function connect_socket() {
  socket = new WebSocket(ws_url);
  socket.on("close", connect_socket); // <- rise from your grave!
  heartbeat();
}

function heartbeat() {
  if (!socket) return;
  if (socket.readyState !== 1) return;
  socket.send("heartbeat");
  setTimeout(heartbeat, 500);
}

connect_socket();

I strongly recommend trying to sort out what's happening on the server end, rather than trying to work around it on the client. 我强烈建议尝试解决服务器端发生的事情,而不是试图在客户端上解决它。

In ouni's solution, heartbeat() wasn't kicking in. It works when it's put in an open event like this: 在ouni的解决方案中,heartbeat()没有被踢进去。当它被放入这样的open事件时它起作用:

let socket = null;

function connect_socket() {
  socket = new WebSocket(ws_url);
  socket.on("close", connect_socket); // <- rise from your grave!
  socket.on("open", heartbeat); // heartbeat when the socket is open
}

function heartbeat() {
  if (!socket) return;
  if (socket.readyState !== 1) return;
  socket.send("heartbeat");
  setTimeout(heartbeat, 500);
}

connect_socket();

According to Mozilla there is a dedicated convention for Ping Pong 根据Mozilla的说法,Ping Pong有一个专门的会议

At any point after the handshake, either the client or the server can choose to send a ping to the other party. 在握手后的任何时刻,客户端或服务器都可以选择向另一方发送ping。 When the ping is received, the recipient must send back a pong as soon as possible. 收到ping后,收件人必须尽快发回pong。 You can use this to make sure that the client is still connected, for example. 例如,您可以使用它来确保客户端仍然连接。

A ping or pong is just a regular frame, but it's a control frame. ping或pong只是一个常规帧,但它是一个控制帧。 Pings have an opcode of 0x9, and pongs have an opcode of 0xA. Pings的操作码为0x9,而pongs的操作码为0xA。 When you get a ping, send back a pong with the exact same Payload Data as the ping (for pings and pongs, the max payload length is 125). 当您获得ping时,请发送一个乒乓,其中包含与ping完全相同的有效负载数据(对于ping和pongs,最大有效负载长度为125)。 You might also get a pong without ever sending a ping; 你也可能在没有发送ping的情况下得到一个乒乓球; ignore this if it happens. 如果它发生,请忽略它。

If you have gotten more than one ping before you get the chance to send a pong, you only send one pong. 如果您在有机会发送乒乓球之前获得了多次ping,则只发送一个乒乓球。

https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers#Pings_and_Pongs_The_Heartbeat_of_WebSockets https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers#Pings_and_Pongs_The_Heartbeat_of_WebSockets

Find more in depth discussion about ping/pong from the browser side here: Sending websocket ping/pong frame from browser 从浏览器端查找有关ping / pong的更多深入讨论: 从浏览器发送websocket ping / pong框架

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM