Mastering WebSocket in WeChat Mini‑Programs: Handshake, Optimization & Real‑World Tips
This article explains the WebSocket handshake protocol, compares short‑polling, long‑polling, and WebSocket connections, and shares practical implementations in WeChat mini‑programs—including authentication, heartbeat, RTT simulation, compression, reconnection strategies, caching, and TCP_NODELAY tuning, complete with code examples.
1. Understanding the WebSocket Handshake
Request Header Features
HTTP must be a 1.1 GET request
Connection header must be "Upgrade"
Upgrade header must be "websocket"
Sec-WebSocket-Key is a base64‑encoded random 16‑byte string
Sec-WebSocket-Protocol records the sub‑protocol (e.g., binary, base64)
Origin indicates the request source
Response Header Features
Status code 101 indicates "Switching Protocols"
Upgrade, Connection, Sec-WebSocket-Protocol match the request headers
Sec-WebSocket-Accept is generated from the Sec-WebSocket-Key
2. Short‑Polling, Long‑Connection, and WebSocket Comparison
1. Short‑Polling
Consumes TCP connections heavily
Headers are repeatedly sent
Initiated as macro‑tasks, limited by the event loop, cannot guarantee timeliness
Generates many ineffective requests
2. Long‑Connection
HTTP keep‑alive allows TCP reuse but does not solve header duplication
Keep‑alive has an expiration; after it ends the server sends probe frames to check TCP validity
HTTP keep‑alive informs the server to persist the TCP connection for subsequent HTTP requests, which is what we call a “long connection”. TCP also has its own keepalive mechanism: after a configurable idle period the server sends probe packets; if no ACK is received after several attempts, the TCP connection is dropped.
(TCP keepalive illustration)
3. WebSocket
Built on TCP like HTTP, but a single HTTP handshake establishes a persistent connection; subsequent communication uses WebSocket frames
Full‑duplex, bidirectional data transfer
Lightweight data format, supports binary, and works over ws and secure wss
3. What I Implemented with WebSocket in WeChat Mini‑Programs
1. Signature Verification and Fault‑Tolerance Strategies
Background and purpose: after the WebSocket handshake, business APIs still require a login state, so a signature verification step is needed; in high‑traffic or server‑crash scenarios, pending requests are downgraded to HTTP.
SocketTask.onOpen(function () {
SocketTask.sendSocketMessage({
msg_type: '验签',
token: 'xxx'
}, (response) => {
console.log(response.user_id, response.access_token);
// channel usable, mark it
global.isSocketAvaliable = true;
})
})2. Heartbeat Keep‑Alive (Reduce TCP Occupancy)
Background and purpose: the client periodically sends an empty packet to keep the socket alive; the server closes the socket if no heartbeat is received within a timeout.
SocketTask.onOpen(function () {
SocketTask.sendSocketMessage({
msg_type: '验签',
token: 'xxx'
}, (response) => {
console.log(response.user_id, response.access_token);
global.isSocketAvaliable = true;
// after successful verification, start sending heartbeats
setInterval(() => {
SocketTask.sendSocketMessage({
msg_type: '心跳'
});
});
})
})3. Simulating RTT for Weak‑Network Optimization
Background and purpose: measuring the RTT of a heartbeat allows estimation of the current TCP RTT, which can be smoothed to compute an RTO for better performance on weak networks.
SocketTask.onOpen(function () {
SocketTask.sendSocketMessage({
msg_type: '验签',
token: 'xxx'
}, (response) => {
console.log(response.user_id, response.access_token);
global.isSocketAvaliable = true;
setInterval(() => {
const begin = Date.now();
SocketTask.sendSocketMessage({
msg_type: '心跳'
}, () => {
const end = Date.now();
const RTT = end - begin;
const smoothedRTO = cal(RTT);
global.smoothedRTO = smoothedRTO;
});
});
})
});4. Snappy Compression (Compared with gzip/zip/7z)
Background and purpose: introduce a third‑party compression library in the mini‑program (at the cost of package size) to reduce the number of bytes transmitted over WebSocket.
import Snappy from 'snappy';
SocketTask.sendSocketMessage = function (msg) {
const encryptedMsg = Snappy.encode(msg);
wx.send(encryptedMsg);
}5. Reconnection (Staggered Reconnection to Avoid Congestion)
Background and purpose: network instability may cause the socket to close; an automatic reconnection mechanism with incremental back‑off prevents a thundering herd.
SocketTask.onClose(function () {
if (retryCount > maxCount) {
return;
}
retryCount++;
setTimeout(() => {
SocketTask.connectSocket();
}, retryCount * 1000 + Math.random() * 1000);
});6. Middleware Cache for Event Reporting
Background and purpose: to reduce payload size, cache repeatable fields on the server; subsequent reports only send non‑repeating fields, and the server merges logs.
SocketTask.sendSocketMessage({
msg_type: '埋点日志',
logs: {
country: 'China', // cacheable field
city: '北京', // cacheable field
platform: '安卓', // cacheable field
click_some_btn: true // dynamic field
},
cacheFields: ['country', 'city', 'platform'] // only sent on first report
});7. Enabling TCP_NODELAY
TCP_NODELAY disables Nagle’s algorithm, which would otherwise combine small TCP packets into larger ones, reducing latency for real‑time data.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
