WebSocket protocol uses frames to transmit data, each frame has a specific format and purpose.
Basic Frame Structure
WebSocket frames consist of multiple fields, format as follows:
shell0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-------+-+-------------+-------------------------------+ |F|R|R|R| opcode|M| Payload len | Extended payload length | |I|S|S|S| (4) |A| (7) | (16/64) | |N|V|V|V| |S| | (if payload len==126/127) | | |1|2|3| |K| | | +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - + | Extended payload length continued, if payload len == 127 | + - - - - - - - - - - - - - - - +-------------------------------+ | |Masking-key, if MASK set to 1 | +-------------------------------+-------------------------------+ | Masking-key (continued) | Payload Data | +-------------------------------- - - - - - - - - - - - - - - - + : Payload Data continued ... : + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | Payload Data continued ... | +---------------------------------------------------------------+
Field Details
FIN (1 bit)
- Indicates whether this is the last fragment of the message
- 1: This is the last fragment
- 0: More fragments follow
RSV1, RSV2, RSV3 (1 bit each)
- Reserved bits, must be 0
- Unless extensions negotiated non-zero values
Opcode (4 bits)
Defines the operation type of the frame:
| Opcode | Meaning |
|---|---|
| 0x0 | Continuation frame |
| 0x1 | Text frame |
| 0x2 | Binary frame |
| 0x8 | Close connection |
| 0x9 | Ping |
| 0xA | Pong |
| 0xB-F | Reserved for extensions |
MASK (1 bit)
- Indicates whether Payload Data is masked
- Frames sent by client must be 1
- Frames sent by server must be 0
Payload Length (7 bits, 7+16 bits, or 7+64 bits)
Payload length, three encoding methods:
- 0-125: Directly represents length
- 126: Next 2 bytes represent length (16-bit unsigned integer)
- 127: Next 8 bytes represent length (64-bit unsigned integer)
Masking-key (32 bits)
- Present when MASK=1
- Used to decode Payload Data
- Client must use random masking key
Payload Data
Actual transmitted data, if masked, needs to be decoded
Masking Algorithm
javascriptfunction unmask(maskedData, maskingKey) { const result = new Uint8Array(maskedData.length); for (let i = 0; i < maskedData.length; i++) { result[i] = maskedData[i] ^ maskingKey[i % 4]; } return result; }
Message Fragmentation
Large messages can be split into multiple frames:
- First frame: FIN=0, Opcode!=0
- Intermediate frames: FIN=0, Opcode=0
- Last frame: FIN=1, Opcode=0
Close Frame
Send close frame when closing connection:
- Opcode=0x8
- Payload contains status code (2 bytes) and optional close reason