自定义解析器
从 Socket.IO v2.0.0 开始,现在可以提供自己的解析器,以控制数据包的编组/解组。
¥Since Socket.IO v2.0.0, it is now possible to provide your own parser, in order to control the marshalling / unmarshalling of packets.
服务器
¥Server
import { Server } from "socket.io";
const io = new Server({
parser: myParser
});
客户端
¥Client
import { io } from "socket.io-client";
const socket = io({
parser: myParser
});
可用的解析器
¥Available parsers
除了 默认解析器 之外,以下是可用解析器的列表:
¥Besides the default parser, here is the list of available parsers:
包 | 描述 |
---|---|
socket.io-circular-parser | 与默认解析器类似,但处理循环引用。 |
socket.io-msgpack-parser | 使用 MessagePack 对数据包进行编码(基于 notepack.io 包)。 |
@skgdev/socket.io-msgpack-javascript | 使用 MessagePack 对数据包进行编码(基于 @msgpack/msgpack 包)。 |
socket.io-json-parser | 使用 JSON.stringify() 和 JSON.parse() 对数据包进行编码。 |
socket.io-cbor-x-parser | 使用 cbor-x 对数据包进行编码。 |
@socket.io/devalue-parser | 使用 devalue 对数据包进行编码。 |
实现你自己的解析器
¥Implementing your own parser
下面是一个使用 JSON.stringify()
和 JSON.parse()
方法的解析器的基本示例:
¥Here is a basic example with a parser that uses the JSON.stringify()
and JSON.parse()
methods:
import { Emitter } from "@socket.io/component-emitter"; // polyfill of Node.js EventEmitter in the browser
class Encoder {
/**
* Encode a packet into a list of strings/buffers
*/
encode(packet) {
return [JSON.stringify(packet)];
}
}
function isObject(value) {
return Object.prototype.toString.call(value) === "[object Object]";
}
class Decoder extends Emitter {
/**
* Receive a chunk (string or buffer) and optionally emit a "decoded" event with the reconstructed packet
*/
add(chunk) {
const packet = JSON.parse(chunk);
if (this.isPacketValid(packet)) {
this.emit("decoded", packet);
} else {
throw new Error("invalid format");
}
}
isPacketValid({ type, data, nsp, id }) {
const isNamespaceValid = typeof nsp === "string";
const isAckIdValid = id === undefined || Number.isInteger(id);
if (!isNamespaceValid || !isAckIdValid) {
return false;
}
switch (type) {
case 0: // CONNECT
return data === undefined || isObject(data);
case 1: // DISCONNECT
return data === undefined;
case 2: // EVENT
return Array.isArray(data) && typeof data[0] === "string";
case 3: // ACK
return Array.isArray(data);
case 4: // CONNECT_ERROR
return isObject(data);
default:
return false;
}
}
/**
* Clean up internal buffers
*/
destroy() {}
}
export const parser = { Encoder, Decoder };
默认解析器
¥The default parser
默认解析器(socket.io-parser
包)的源代码可以在这里找到:https://github.com/socketio/socket.io-parser
¥The source code of the default parser (the socket.io-parser
package) can be found here: https://github.com/socketio/socket.io-parser
输出示例:
¥Example of output:
基本触发
¥basic emit
socket.emit("test", 42);
将被编码为:
¥will be encoded as:
2["test",42]
||
|└─ JSON-encoded payload
└─ packet type (2 => EVENT)
使用二进制、确认和自定义命名空间触发
¥emit with binary, acknowledgement and custom namespace
socket.emit("test", Uint8Array.from([42]), () => {
console.log("ack received");
});
将被编码为:
¥will be encoded as:
51-/admin,13["test",{"_placeholder":true,"num":0}]
|||| || └─ JSON-encoded payload with placeholders for binary attachments
|||| |└─ acknowledgement id
|||| └─ separator
|||└─ namespace (not included when it's the main namespace)
||└─ separator
|└─ number of binary attachments
└─ packet type (5 => BINARY EVENT)
and an additional attachment (the extracted Uint8Array)
优点:
¥Pros:
然后对二进制附件进行 Base64 编码,因此该解析器与 不支持数组缓冲区 的浏览器兼容,例如 IE9
¥the binary attachments is then base64-encoded, so this parser is compatible with browsers that do not support Arraybuffers, like IE9
缺点:
¥Cons:
具有二进制内容的数据包作为两个不同的 WebSocket 帧发送(如果已建立 WebSocket 连接)
¥packets with binary content are sent as two distinct WebSocket frames (if the WebSocket connection is established)
msgpack 解析器
¥The msgpack parser
该解析器使用 MessagePack 序列化格式。
¥This parser uses the MessagePack serialization format.
该解析器的源代码可以在这里找到:https://github.com/socketio/socket.io-msgpack-parser
¥The source code of this parser can be found here: https://github.com/socketio/socket.io-msgpack-parser
使用示例:
¥Sample usage:
服务器
¥Server
import { Server } from "socket.io";
import customParser from "socket.io-msgpack-parser";
const io = new Server({
parser: customParser
});
客户端(Node.js)
¥Client (Node.js)
import { io } from "socket.io-client";
import customParser from "socket.io-msgpack-parser";
const socket = io("https://example.com", {
parser: customParser
});
在浏览器中,现在有一个包含此解析器的官方包:
¥In the browser, there is now an official bundle which includes this parser:
cdnjs:https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.7.5/socket.io.msgpack.min.js
jsDelivr:https://cdn.jsdelivr.net/npm/socket.io-client@4.7.5/dist/socket.io.msgpack.min.js
拆包:https://unpkg.com/socket.io-client@4.7.5/dist/socket.io.msgpack.min.js
¥unpkg: https://unpkg.com/socket.io-client@4.7.5/dist/socket.io.msgpack.min.js
在这种情况下,你不需要指定 parser
选项。
¥In that case, you don't need to specify the parser
option.
优点:
¥Pros:
包含二进制内容的数据包作为单个 WebSocket 帧发送(如果已建立 WebSocket 连接)
¥packets with binary content are sent as one single WebSocket frame (if the WebSocket connection is established)
可能会导致较小的有效负载(尤其是在使用大量数字时)
¥may result in smaller payloads (especially when using a lot of numbers)
缺点:
¥Cons:
与 不支持数组缓冲区 的浏览器不兼容,例如 IE9
¥incompatible with browsers that do not support Arraybuffers, like IE9
在浏览器的“网络”选项卡中更难调试
¥harder to debug in the Network tab of the browser
请注意,socket.io-msgpack-parser
依赖于 notepack.io
MessagePack 实现。此实现主要关注性能和最小包大小,因此不支持扩展类型等功能。对于基于 官方 JavaScript 实现 的解析器,请检查 这个包。
¥Please note that socket.io-msgpack-parser
relies on the notepack.io
MessagePack implementation. This implementation mainly focuses on performance and minimal bundle size, and thus does not support features like extension types. For a parser based on the official JavaScript implementation, please check this package.