Пользовательский парсер
Начиная с Socket.IO v2.0.0, теперь можно предоставить собственный парсер, чтобы управлять кодированием/декодированием пакетов.
Сервер
const httpServer = require("http").createServer();
const io = require("socket.io")(httpServer, {
parser: myParser
}); |
Клиент
const socket = io({
parser: myParser
}); |
Реализация собственного парсера
Вот базовый пример с парсером, который использует методы JSON.stringify() и JSON.parse().
const Emitter = require("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)];
}
}
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 || typeof data === "object";
case 1: // DISCONNECT
return data === undefined;
case 2: // EVENT
return Array.isArray(data) && data.length > 0;
case 3: // ACK
return Array.isArray(data);
case 4: // CONNECT_ERROR
return typeof data === "object";
default:
return false;
}
}
/**
* Clean up internal buffers
*/
destroy() {}
}
module.exports = { Encoder, Decoder }; |
По умолчанию парсер
Исходный код парсера по умолчанию (пакет socket.io-parser) можно найти здесь: https://github.com/socketio/socket.io-parser
Пример вывода:
- основная отправка
socket.emit("test", 42); |
будет закодировано как:
2["test",42] || |└─ JSON-encoded payload └─ packet type (2 => EVENT) |
- отправка с бинарными данными, подтверждением и пользовательским пространством имен
socket.emit("test", Uint8Array.from([42]), () => {
console.log("ack received");
}); |
будет закодировано как:
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) |
Преимущества:
- приложения с бинарными данными затем кодируются в base64, поэтому этот парсер совместим с браузерами, которые не поддерживают Arraybuffer, например, IE9
Недостатки:
- пакеты с бинарным содержимым отправляются как два отдельных кадра WebSocket (если соединение WebSocket установлено)
Парсер msgpack
Исходный код этого парсера можно найти здесь: https://github.com/darrachequesne/socket.io-msgpack-parser
Пример использования:
Сервер
const httpServer = require("http").createServer();
const io = require("socket.io")(httpServer, {
parser: require("socket.io-msgpack-parser")
}); |
Клиент (Node.js)
const socket = require("socket.io-client")("https://example.com", {
parser: require("socket.io-msgpack-parser")
}); |
В браузере теперь есть официальный пакет, который включает этот парсер:
- https://cdn.socket.io/3.1.1/socket.io.msgpack.min.js
- cdnjs: https://cdnjs.cloudflare.com/ajax/libs/socket.io/3.1.1/socket.io.msgpack.min.js
- jsDelivr: https://cdn.jsdelivr.net/npm/socket.io-client@3.1.1/dist/socket.io.msgpack.min.js
- unpkg: https://unpkg.com/socket.io-client@3.1.1/dist/socket.io.msgpack.min.js
В этом случае вам не нужно указывать параметр parser.
Преимущества:
- пакеты с бинарным содержимым отправляются как один единственный кадр WebSocket (если соединение WebSocket установлено)
- может привести к меньшим объёмам данных (особенно при использовании большого количества чисел)
Недостатки:
- несовместим с браузерами, которые не поддерживают Arraybuffer, например, IE9
- сложнее отлаживать в вкладке «Сеть» браузера
© 2014–2021 Automattic
Licensed under the MIT License.
https://socket.io/docs/v3/custom-parser