How to implement Ping/Pong request for webSocket connection alive in javascript?
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:
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.
Yes, there are ping/pong frames in websockets. Here is an example using the ws
module, where the server is initiating the ping request:
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);