在实时数据交互场景中,WebSocket是常用的通信协议,有时我们需要根据运行时的参数动态构建连接地址,同时处理服务端发送的二进制格式消息,比如音视频流、压缩数据包等。

动态构建WebSocket连接的核心步骤
动态构建连接的关键在于连接地址的拼接逻辑,以及连接状态的管理。首先需要明确动态参数的来源,比如用户ID、房间号、时间戳等,然后按照约定的格式拼接完整的WebSocket地址。
1. 地址拼接与连接初始化
假设我们需要根据用户所在的房间ID动态构建连接,基础地址为ws://ipipp.com/ws,房间ID从运行时变量中获取,拼接逻辑如下:
// 动态参数
const roomId = 'room_123';
const userId = 'user_456';
// 拼接连接地址
const wsUrl = `ws://ipipp.com/ws?roomId=${roomId}&userId=${userId}`;
// 初始化WebSocket连接
let socket = null;
function initWebSocket() {
if (socket && socket.readyState === WebSocket.OPEN) {
return;
}
socket = new WebSocket(wsUrl);
// 绑定连接事件
socket.onopen = () => {
console.log('WebSocket连接已建立');
};
}
initWebSocket();
2. 连接异常处理与重连机制
动态构建的连接可能因为网络波动、参数失效等问题断开,需要添加自动重连逻辑,避免连接断开后无法恢复。
let reconnectTimer = null;
const RECONNECT_INTERVAL = 3000; // 重连间隔3秒
const MAX_RECONNECT_COUNT = 5; // 最大重连次数
let reconnectCount = 0;
socket.onerror = (error) => {
console.error('WebSocket连接出错:', error);
};
socket.onclose = () => {
console.log('WebSocket连接已关闭');
// 触发重连
if (reconnectCount < MAX_RECONNECT_COUNT) {
reconnectTimer = setTimeout(() => {
reconnectCount++;
console.log(`第${reconnectCount}次重连`);
initWebSocket();
}, RECONNECT_INTERVAL);
} else {
console.log('达到最大重连次数,停止重连');
}
};
接收并解析二进制消息
WebSocket默认支持接收字符串和二进制两种格式的消息,要接收二进制消息,需要先设置binaryType属性,再对接收到的数据进行解析。
1. 配置二进制消息类型
WebSocket实例的binaryType属性可以设置为arraybuffer或者blob,arraybuffer更适合前端直接操作二进制数据,blob适合需要保存为文件或者转成其他格式的场景。
// 设置接收二进制消息的格式为ArrayBuffer
socket.binaryType = 'arraybuffer';
socket.onmessage = (event) => {
// 判断消息类型
if (typeof event.data === 'string') {
// 处理字符串消息
console.log('收到字符串消息:', event.data);
} else if (event.data instanceof ArrayBuffer) {
// 处理二进制ArrayBuffer消息
handleBinaryMessage(event.data);
}
};
2. 解析二进制消息示例
假设服务端发送的二进制消息前4个字节是消息类型标识,后续字节是实际数据内容,解析逻辑如下:
function handleBinaryMessage(buffer) {
// 创建DataView操作ArrayBuffer
const dataView = new DataView(buffer);
// 读取前4个字节的消息类型(假设是32位无符号整数)
const messageType = dataView.getUint32(0, true); // true表示小端序
// 获取剩余的实际数据
const dataBuffer = buffer.slice(4);
// 根据消息类型处理数据
switch (messageType) {
case 1:
// 处理文本类二进制数据,转成字符串
const textDecoder = new TextDecoder('utf-8');
const text = textDecoder.decode(dataBuffer);
console.log('收到文本类二进制消息:', text);
break;
case 2:
// 处理数值类数据,假设后续是8个字节的双精度浮点数
const value = dataView.getFloat64(4, true);
console.log('收到数值类二进制消息:', value);
break;
default:
console.log('未知类型的二进制消息');
}
}
完整示例整合
将上述逻辑整合后,完整的动态构建连接并接收二进制消息的代码如下:
// 动态参数
const roomId = 'room_123';
const userId = 'user_456';
const wsUrl = `ws://ipipp.com/ws?roomId=${roomId}&userId=${userId}`;
let socket = null;
let reconnectTimer = null;
const RECONNECT_INTERVAL = 3000;
const MAX_RECONNECT_COUNT = 5;
let reconnectCount = 0;
function initWebSocket() {
if (socket && socket.readyState === WebSocket.OPEN) {
return;
}
socket = new WebSocket(wsUrl);
// 设置二进制消息类型
socket.binaryType = 'arraybuffer';
socket.onopen = () => {
console.log('WebSocket连接已建立');
// 重置重连计数
reconnectCount = 0;
if (reconnectTimer) {
clearTimeout(reconnectTimer);
reconnectTimer = null;
}
};
socket.onmessage = (event) => {
if (typeof event.data === 'string') {
console.log('收到字符串消息:', event.data);
} else if (event.data instanceof ArrayBuffer) {
handleBinaryMessage(event.data);
}
};
socket.onerror = (error) => {
console.error('WebSocket连接出错:', error);
};
socket.onclose = () => {
console.log('WebSocket连接已关闭');
if (reconnectCount < MAX_RECONNECT_COUNT) {
reconnectTimer = setTimeout(() => {
reconnectCount++;
console.log(`第${reconnectCount}次重连`);
initWebSocket();
}, RECONNECT_INTERVAL);
} else {
console.log('达到最大重连次数,停止重连');
}
};
}
function handleBinaryMessage(buffer) {
const dataView = new DataView(buffer);
const messageType = dataView.getUint32(0, true);
const dataBuffer = buffer.slice(4);
switch (messageType) {
case 1:
const textDecoder = new TextDecoder('utf-8');
const text = textDecoder.decode(dataBuffer);
console.log('收到文本类二进制消息:', text);
break;
case 2:
const value = dataView.getFloat64(4, true);
console.log('收到数值类二进制消息:', value);
break;
default:
console.log('未知类型的二进制消息');
}
}
// 初始化连接
initWebSocket();
注意事项
- 动态拼接地址时需要对参数进行编码,避免特殊字符导致连接失败,比如使用
encodeURIComponent处理参数值。 - 二进制消息的解析需要和前端约定好格式,比如字节序、字段长度、编码方式等,否则会出现解析错误。
- 不需要使用连接时,要主动调用
socket.close()关闭连接,避免占用服务端资源。 - 如果是HTTPS环境,WebSocket地址需要使用
wss://协议,不能使用ws://。
WebSocket动态构建连接二进制消息ArrayBuffer修改时间:2026-06-21 06:57:36