WebSocket Frames: Text, Binary, Close, Ping, Pong
In this tutorial, you will learn about Websocket Frames: Text, Binary, Close, Ping, Pong. We cover key concepts, practical examples, and best practices to help you master this topic.
WebSocket communication uses a frame-based protocol. Each frame has an opcode indicating its type: text (0x1), binary (0x2), close (0x8), ping (0x9), or pong (0xA). Control frames (close, ping, pong) can interleave with data frames.
What You'll Learn
- Frame structure: opcode, mask, payload length, masking key
- Text vs Binary frames
- Close frame status codes and reasons
- Ping and Pong for keepalive
- Frame fragmentation (continuation frames)
Why It Matters
Understanding frames helps debug low-level issues, implement custom WebSocket servers, and optimize message handling. Frame manipulation is essential for proxy and gateway implementations.
Real-World Use
Discord uses binary frames for voice data and text frames for chat. Trading platforms use binary frames for price data. Ping-pong is standard for connection keepalive in all production WebSocket implementations.
flowchart LR
Frame[WebSocket Frame] --> Opcode[Opcode: 4 bits]
Frame --> Mask[Mask: 1 bit]
Frame --> Length[Payload Length: 7/7+16/7+64 bits]
Frame --> Masking[Masking Key: 0 or 4 bytes]
Frame --> Payload[Payload Data]
Opcode --> Text[0x1: Text]
Opcode --> Binary[0x2: Binary]
Opcode --> Close[0x8: Close]
Opcode --> Ping[0x9: Ping]
Opcode --> Pong[0xA: Pong]
Teacher Mindset
Frames are the atomic unit of WebSocket communication. Text frames carry UTF-8 data. Binary frames carry arbitrary bytes. Ping-pong frames keep the connection alive. Close frames terminate the connection gracefully.
Code Examples
// Example 1: Sending different frame types
const ws = new WebSocket('ws://localhost:8080');
// Text frame (UTF-8 string)
ws.send('Hello, world!');
// Binary frame (ArrayBuffer)
const buffer = new ArrayBuffer(4);
const view = new DataView(buffer);
view.setUint32(0, 42);
ws.send(buffer);
// Binary frame (Blob)
ws.send(new Blob([buffer]));
// Binary frame (typed array)
ws.send(new Uint8Array([0x00, 0x01, 0x02]));
// Example 2: Handling close frames with status codes
const ws = new WebSocket('ws://localhost:8080');
ws.onclose = (event) => {
console.log(`Closed: ${event.code} - ${event.reason}`);
// 1000: Normal closure
// 1001: Going away (server restart)
// 1008: Policy violation
// 1011: Unexpected error
};
// Server-side close with reason
ws.close(4001, 'Session expired');
// Example 3: Server ping-pong keepalive
const WebSocket = require('ws');
const server = new WebSocket.Server({ port: 8080 });
server.on('connection', (ws) => {
ws.isAlive = true;
ws.on('pong', () => {
ws.isAlive = true;
});
// Ping every 10 seconds
const interval = setInterval(() => {
if (ws.isAlive === false) {
console.log('Terminating dead connection');
return ws.terminate();
}
ws.isAlive = false;
ws.ping();
}, 10000);
ws.on('close', () => clearInterval(interval));
});
Common Mistakes
- Closing connections without a status code (should send 1000 for normal)
- Using text frames for binary data (causes UTF-8 encoding errors)
- Not implementing ping-pong, leading to zombie connections
- Sending frames larger than the server max frame size
- Forgetting that client-to-server frames must be masked
Practice
- Send a text, binary, and ping frame from a WebSocket client.
- Handle close frames with different status codes.
- Implement server-side ping-pong with timeouts.
- Fragment a large message into multiple continuation frames.
- Challenge: Write a program that inspects and prints raw frame data (opcode, length, payload).
FAQ
Mini Project
Build a WebSocket server that distinguishes between text and binary frames. Echo text frames back to the sender. For binary frames, interpret the first 4 bytes as a 32-bit integer and send back its square. Implement ping-pong keepalive.
What's Next
Next, you will learn about the differences between ws:// and wss:// protocols.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro