Why WebSocket Heartbeat Is Essential and How to Implement It

This article explains why heartbeat detection is crucial for WebSocket connections, describes the underlying Ping/Pong mechanism, details server and client configuration parameters, and provides complete code examples for implementing reliable heartbeat and reconnection logic.

Open Source Tech Hub
Open Source Tech Hub
Open Source Tech Hub
Why WebSocket Heartbeat Is Essential and How to Implement It

Why Heartbeat Detection Is Required

When a WebSocket client closes normally it sends a FIN packet, allowing the server to trigger the onClose callback immediately. In extreme situations—power loss, network cable removal, router failure, or aggressive firewall time‑outs—the client cannot send FIN, so the server remains unaware that the connection has disappeared. A periodic heartbeat lets the server detect such silent drops promptly and close the socket.

Heartbeat Principle

The client transmits a small data packet at a regular interval (commonly less than 60 seconds). The server treats the absence of a heartbeat for a configured timeout as a lost connection, closes the socket, and invokes onClose. This also keeps idle connections from being terminated by intermediate firewalls.

WebSocket Ping/Pong Frames

WebSocket defines two control frames: Ping (opcode 0x9) and Pong (opcode 0xA). When a Ping frame is received, the peer must reply with a Pong frame.

Client‑Side Implementation

this.heartbeatTimer = setInterval(() => {
    ws.send('{"event":"ping","content":"ping heartbeat"}');
}, originData.ping_interval);

Server‑Side Implementation (GatewayWorker)

$gateway = new Gateway("websocket://0.0.0.0:8783");
$gateway->pingInterval = 55;               // seconds between heartbeats
$gateway->pingNotResponseLimit = 0;        // 0 = client may stay silent
$gateway->pingData = '{"type":"ping"}'; // payload sent to client

Key Configuration Parameters

Gateway::$pingInterval

– heartbeat interval in seconds; set to 0 to disable heartbeats. Gateway::$pingNotResponseLimit – number of consecutive missed intervals tolerated before the server closes the connection; 0 disables the server‑side requirement. Gateway::$pingData – JSON payload the server sends as a heartbeat; the client may ignore it.

Practical Notes

The first heartbeat after a successful connection may occur earlier than the configured interval.

If the client has recently sent any data, the server may skip a heartbeat and send the next one after roughly 1.5 * pingInterval seconds.

When the client initiates heartbeats, pingNotResponseLimit should be set greater than 0 so the server can detect dead connections promptly.

Reconnection Strategy

Regardless of which side sends the heartbeat, disconnections can still happen (browser tab suspension, device sleep, network changes, router policies, etc.). Clients must listen for the onclose event and establish a new WebSocket connection, optionally using an exponential back‑off delay, because the server cannot reconnect on behalf of the client.

Complete Code Samples

Server Configuration (example, not recommended for production)

'pingInterval' => 30,
'pingNotResponseLimit' => 0,
'pingData' => '{"event":"ping","msg":"我是服务端主动心跳检测"}',

Client Implementation (recommended)

let timeout = null;
let ws = new WebSocket("ws://127.0.0.1:8783");
ws.onopen = function(evt) {
    const payload = {
        "event": "join",
        "mode": 1,
        "group_id": 0,
        "from_user_id": "10086",
        "from_username": "开源技术小栈",
        "to_user_id": "10000",
        "content": "加入会话"
    };
    ws.send(JSON.stringify(payload));
};
ws.onmessage = function(evt) {
    console.log("【开源技术小栈】接受消息: " + evt.data);
    const obj = JSON.parse(evt.data);
    if (obj.data.event === 'init') {
        sendHeartbeat();
    }
};
function sendHeartbeat() {
    console.log('客户端定时发送心跳');
    ws.send('{"event":"ping","content":"开源技术小栈我在线呢!"}');
    timeout = setTimeout(sendHeartbeat, 3000);
}
ws.onclose = function() {
    clearTimeout(timeout);
    console.log('没有网了,睡觉去了');
};

References

Source code repository: https://github.com/Tinywan/webman-admin

Server heartbeat console output
Server heartbeat console output
Client heartbeat console output
Client heartbeat console output
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

BackendWebSocketPHPHeartbeatconnectionreconnection
Open Source Tech Hub
Written by

Open Source Tech Hub

Sharing cutting-edge internet technologies and practical AI resources.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.