skip to content

Ping/Pong and Close

Ping and pong frames for liveness, close frames and their status codes, clean versus abrupt shutdown. Interviewers ask because a half-open socket looks healthy until a write finally fails.

part ofWebSocketsoverview, primer and where to startread it →
on this pageshow

questions

4

In the WebSocket protocol, what must an endpoint do when it receives a Ping control frame, and what does that exchange prove?

level: juniorimportance: must knowfreq 68%

answer

  1. two control frames, not data frames
  2. the answer echoes the probe
  3. either endpoint may send one
  4. capped at 125 bytes, unfragmentable
  5. %x9 answered by %xA

basics

~20 s

A WebSocket endpoint that receives a Ping frame (opcode %x9) must answer with a Pong frame (opcode %xA) carrying identical application data. A completed round trip proves the peer's process read a frame and wrote one back.

solid answer

~50 s

Ping (`%x9`) and Pong (`%xA`) are WebSocket control frames, not data frames. An endpoint that receives a Ping must send a Pong in response, unless it has already received a Close frame, and it should do so as soon as is practical. The Pong must carry the identical application data the Ping carried, which is what lets the prober correlate an answer with a specific probe and time the round trip. Either side may send a Ping; there is no client-only rule. A Pong may also be sent unsolicited, as a one-way heartbeat that expects no answer. Both are control frames, so each is capped at 125 bytes of payload and may not be fragmented. What a completed exchange proves is narrow but real: the peer read a frame and wrote one back, so both directions are live.

code

pseudocode · 15 lines
pseudocode
// prober: send a probe with a correlatable payload
probe_id = next_sequence_number()
send control frame PING with payload = probe_id
sent_at[probe_id] = now()

// peer: the required answer
on receive control frame PING with payload p:
    if close_frame_already_received:
        return                       // no answer is owed once closing
    send control frame PONG with payload = p   // identical bytes

// prober: correlate the answer to the probe
on receive control frame PONG with payload p:
    round_trip = now() - sent_at[p]
    clear sent_at[p]

go deeper

for a junior

Recall the pair and the echo rule: a Ping frame is answered by a Pong frame carrying the same bytes, and either endpoint may send one.

for a middle

Explain why the echo exists — it makes the payload a correlation token, so a Pong can be matched to one probe and timed, which is what turns a keepalive into a latency measurement.

for a senior

Be precise about what a returned Pong proves: frames move in both directions and the peer's read loop runs. It is not evidence that queued application work is progressing.

for a principal

The trade-off you own is probe cost against detection latency across a whole fleet of idle connections, and whether liveness is measured at the protocol layer or by an application-level acknowledgement that also proves work is progressing.

## Two kinds of frame Every WebSocket frame is either a **data frame**, carrying a message the application sent, or a **control frame**, carrying protocol housekeeping. Ping (`opcode %x9`), Pong (`opcode %xA`) and Close (`opcode %x8`) are the control frames defined by `RFC 6455`. They exist so that the two endpoints can talk *about* the connection while it is carrying traffic, without the application having to invent a message type for it. A Ping frame is a request for proof of life. An endpoint that receives one **must** send a Pong back, with one stated exception: if it has already received a Close frame from that peer, the connection is on its way down and no answer is owed. The specification also says the Pong should be sent as soon as is practical — a recommendation, not a hard deadline, which is exactly why your own timeout is a judgement call rather than a number the protocol hands you. ## Why the echo rule matters Two properties turn this pair from decoration into a usable instrument: - **The Pong echoes the Ping.** A Pong sent in answer to a Ping must carry the *identical* application data the Ping carried. The payload is opaque to the protocol, so the prober can put a sequence number, a counter or a monotonic timestamp in it. - **The echo makes the payload a correlation token.** Without it, a returning Pong would be anonymous and you could not tell which of three outstanding probes it answered, nor measure a round trip against the right send time. - **Either endpoint may probe.** Ping is not a client-side mechanism; a server that holds ten thousand idle connections is usually the side that most needs one. That is why "what does a Pong contain?" is a real interview question and not trivia: the answer is the difference between a keepalive and a latency probe. ## Unsolicited Pong frames A Pong may legally be sent that no Ping asked for. The specification calls this a unidirectional heartbeat, and no response to it is expected. It is the right tool when you want to announce your own liveness and keep bytes moving on an otherwise silent path, but do not need anything back. Note what it does and does not prove: an unsolicited Pong tells the *peer* that you are writing, and tells *you* nothing at all. ## Size and fragmentation Control frames are constrained in two ways that data frames are not: 1. A control frame **must** have a payload length of 125 bytes or less. A probe token therefore has to be small — a counter or a timestamp fits comfortably, a serialized diagnostic object does not. 2. A control frame **must not** be fragmented. It arrives whole or not at all, which is what allows it to be interleaved with a large message in flight without corrupting it. ## What the exchange proves — and what it does not A returned Pong proves that the peer's process read a frame off the connection and wrote one back. That is a stronger statement than it sounds, because it exercises both directions and the peer's read loop, not just the network path. It is also narrower than candidates usually claim: - It does **not** prove the peer's application logic is healthy — a process stuck behind a saturated work queue can still answer control frames if its protocol layer is separate. - It does **not** prove that an earlier data message was processed, only that frames are moving. - A *missing* Pong is weak evidence on its own: one frame can be lost or delayed under load, which is why liveness decisions are made over several consecutive probes rather than one. ## Four things called "ping" | What it is | Where it lives | What answers it | |---|---|---| | WebSocket Ping frame (`%x9`) | inside the WebSocket connection | a Pong frame (`%xA`) with identical payload | | HTTP/2 PING frame | the transport beneath a socket bootstrapped over HTTP/2 | a PING with the ACK flag, handled by the transport, invisible to the socket | | TCP keepalive probe | the operating system's transport stack | an acknowledgement from the peer's stack, not its application | | An application "ping" message | a data frame the application defined itself | whatever the application defines | Only the first is the mechanism this question is about, and only the first and the last tell you anything about the peer's *application*. Saying "we have keepalive on" without naming which of these four you mean is the fastest way to a follow-up you cannot answer.

  • When is a WebSocket endpoint not obliged to answer a Ping frame?
    When it has already received a Close frame from that peer. The closing handshake is under way, so no Pong is owed. Outside that case the answer is required, and the specification recommends sending it as soon as is practical rather than batching it behind queued application work.
  • What is an unsolicited Pong frame for?
    It is a legal one-way heartbeat: an endpoint announces that it is still writing, and expects nothing back. It keeps bytes on an otherwise silent path and signals liveness cheaply, but it gives the *sender* no information — only a Ping answered by a Pong tells you the peer is reading and writing.
  • How large can a probe payload be?
    125 bytes at most, because Ping and Pong are control frames and every control frame is capped at that length and may not be fragmented. A counter or a timestamp fits; anything structured does not. If you need to carry diagnostics, that belongs in an application message, not in the probe.

A shouted challenge with an agreed word in it: any reply proves someone is listening, but only a reply that repeats your word proves it answered you, and not a stale echo of the last challenge.

saying these in an interview costs you the question

  • Says only the client may send a WebSocket Ping frame.
  • Thinks the Pong may carry any payload, or none at all.
  • Confuses a WebSocket Ping frame with an HTTP/2 PING frame beneath it.
  • Claims transport-level keepalive proves the peer's application is reading.
  • Believes a Ping frame can carry a large diagnostic payload.
open as a page

In a WebSocket connection, what happens on the wire between one endpoint deciding to close and the TCP connection actually ending?

level: middleimportance: must knowfreq 60%

basics

~20 s

The closing endpoint sends a Close frame and stops sending data; the peer sends a Close frame back. Only once both directions have exchanged one does the transport go: the server closes the TCP connection and the client waits for that close.

open as a page

In the WebSocket protocol, which close status codes must never appear in a Close frame on the wire, and why do they exist?

level: middleimportance: should knowfreq 50%

basics

~20 s

Codes 1005, 1006 and 1015 are reserved and must never be sent in a Close frame. They exist only so a local client API can report a Close frame with no status, a connection that ended with no Close frame at all, or a failed TLS handshake.

open as a page

A WebSocket to a turbine maintenance console has carried no traffic for an hour and still looks connected; how do you establish whether it is alive?

level: seniorimportance: should knowfreq 55%

basics

~20 s

Send Ping frames on a timer and require a Pong within a deadline. A silent TCP connection cannot distinguish a healthy idle link from one whose state something along the path discarded, so only a probe — judged over several consecutive misses — settles it.

open as a page