自定义解析器

从 Socket.IO v2.0.0 开始,现在可以提供自己的解析器,以控制数据包的编组/解组。

服务器

  1. import { Server } from "socket.io";
  2. const io = new Server({
  3. parser: myParser
  4. });

客户端

  1. import { io } from "socket.io-client";
  2. const socket = io({
  3. parser: myParser
  4. });

Available parsers

Besides the default parser, here is the list of available parsers:

PackageDescription
socket.io-circular-parserSimilar to the default parser, but handles circular references.
socket.io-msgpack-parserUses MessagePack to encode the packets (based on the notepack.io package).
@skgdev/socket.io-msgpack-javascriptUses MessagePack to encode the packets (based on the @msgpack/msgpack package).
socket.io-json-parserUses JSON.stringify() and JSON.parse() to encode the packets.
socket.io-cbor-x-parserUses cbor-x to encode the packets.
@socket.io/devalue-parserUses devalue to encode the packets.

实现自己的解析器

这是一个使用JSON.stringify()JSON.parse()方法的解析器的基本示例:

  1. import { Emitter } from "@socket.io/component-emitter"; // polyfill of Node.js EventEmitter in the browser
  2. class Encoder {
  3. /**
  4. * Encode a packet into a list of strings/buffers
  5. */
  6. encode(packet) {
  7. return [JSON.stringify(packet)];
  8. }
  9. }
  10. function isObject(value) {
  11. return Object.prototype.toString.call(value) === "[object Object]";
  12. }
  13. class Decoder extends Emitter {
  14. /**
  15. * Receive a chunk (string or buffer) and optionally emit a "decoded" event with the reconstructed packet
  16. */
  17. add(chunk) {
  18. const packet = JSON.parse(chunk);
  19. if (this.isPacketValid(packet)) {
  20. this.emit("decoded", packet);
  21. } else {
  22. throw new Error("invalid format");
  23. }
  24. }
  25. isPacketValid({ type, data, nsp, id }) {
  26. const isNamespaceValid = typeof nsp === "string";
  27. const isAckIdValid = id === undefined || Number.isInteger(id);
  28. if (!isNamespaceValid || !isAckIdValid) {
  29. return false;
  30. }
  31. switch (type) {
  32. case 0: // CONNECT
  33. return data === undefined || isObject(data);
  34. case 1: // DISCONNECT
  35. return data === undefined;
  36. case 2: // EVENT
  37. return Array.isArray(data) && typeof data[0] === "string";
  38. case 3: // ACK
  39. return Array.isArray(data);
  40. case 4: // CONNECT_ERROR
  41. return isObject(data);
  42. default:
  43. return false;
  44. }
  45. }
  46. /**
  47. * Clean up internal buffers
  48. */
  49. destroy() {}
  50. }
  51. export const parser = { Encoder, Decoder };

默认解析器

默认解析器(socket.io-parser包)的源代码可以在这里找到:https://github.com/socketio/socket.io-parser

输出示例:

  • 基本 emit
  1. socket.emit("test", 42);

将被编码为:

  1. 2["test",42]
  2. ||
  3. |└─ JSON-encoded payload
  4. └─ packet type (2 => EVENT)
  • 使用二进制、确认和自定义命名空间发出
  1. socket.emit("test", Uint8Array.from([42]), () => {
  2. console.log("ack received");
  3. });

将被编码为:

  1. 51-/admin,13["test",{"_placeholder":true,"num":0}]
  2. |||| || └─ JSON-encoded payload with placeholders for binary attachments
  3. |||| |└─ acknowledgement id
  4. |||| └─ separator
  5. |||└─ namespace (not included when it's the main namespace)
  6. ||└─ separator
  7. |└─ number of binary attachments
  8. └─ packet type (5 => BINARY EVENT)
  9. and an additional attachment (the extracted Uint8Array)

优点:

  • 二进制附件是 base64 编码的,所以这个解析器与不支持 Arraybuffers的浏览器兼容,比如 IE9

缺点:

  • 具有二进制内容的数据包作为两个不同的 WebSocket 帧发送(如果建立了 WebSocket 连接)

msgpack 解析器

此解析器使用MessagePack序列化格式。

这个解析器的源代码可以在这里找到:https://github.com/socketio/socket.io-msgpack-parser

示例用法:

服务器

  1. import { Server } from "socket.io";
  2. import customParser from "socket.io-msgpack-parser";
  3. const io = new Server({
  4. parser: customParser
  5. });

客户端 (Node.js)

  1. import { io } from "socket.io-client";
  2. import customParser from "socket.io-msgpack-parser";
  3. const socket = io("https://example.com", {
  4. parser: customParser
  5. });

在浏览器中,现在有一个包含此解析器的官方包:

在这种情况下,您不需要指定parser配置项。

优点:

  • 具有二进制内容的数据包作为单个 WebSocket 帧发送(如果建立了 WebSocket 连接)
  • 可能会导致更小的有效载荷(尤其是在使用大量数字时)

缺点:

自定义解析器 - 图1信息

请注意,这socket.io-msgpack-parser依赖于notepack.ioMessagePack 实现。此实现主要关注性能和最小包大小,因此不支持扩展类型等功能。对于基于官方 JavaScript 实现的解析器,请查看这个包