Ir al contenido principal
Versión: 4.x

Parser personalizado

Desde Socket.IO v2.0.0, ahora es posible proporcionar tu propio parser, para controlar el marshalling / unmarshalling de paquetes.

Servidor

import { Server } from "socket.io";

const io = new Server({
parser: myParser
});

Cliente

import { io } from "socket.io-client";

const socket = io({
parser: myParser
});

Parsers disponibles​

Además del parser por defecto, aquí está la lista de parsers disponibles:

PaqueteDescripción
socket.io-circular-parserSimilar al parser por defecto, pero maneja referencias circulares.
socket.io-msgpack-parserUsa MessagePack para codificar los paquetes (basado en el paquete notepack.io).
@skgdev/socket.io-msgpack-javascriptUsa MessagePack para codificar los paquetes (basado en el paquete @msgpack/msgpack).
socket.io-json-parserUsa JSON.stringify() y JSON.parse() para codificar los paquetes.
socket.io-cbor-x-parserUsa cbor-x para codificar los paquetes.
@socket.io/devalue-parserUsa devalue para codificar los paquetes.

Implementando tu propio parser​

Aquí hay un ejemplo básico con un parser que usa los métodos JSON.stringify() y JSON.parse():

import { Emitter } from "@socket.io/component-emitter"; // polyfill de Node.js EventEmitter en el navegador

class Encoder {
/**
* Codificar un paquete en una lista de strings/buffers
*/
encode(packet) {
return [JSON.stringify(packet)];
}
}

function isObject(value) {
return Object.prototype.toString.call(value) === "[object Object]";
}

class Decoder extends Emitter {
/**
* Recibir un fragmento (string o buffer) y opcionalmente emitir un evento "decoded" con el paquete reconstruido
*/
add(chunk) {
const packet = JSON.parse(chunk);
if (this.isPacketValid(packet)) {
this.emit("decoded", packet);
} else {
throw new Error("formato inválido");
}
}
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;
}
}
/**
* Limpiar buffers internos
*/
destroy() {}
}

export const parser = { Encoder, Decoder };

El parser por defecto​

El código fuente del parser por defecto (el paquete socket.io-parser) se puede encontrar aquí: https://github.com/socketio/socket.io-parser

Ejemplo de salida:

  • emit básico
socket.emit("test", 42);

será codificado como:

2["test",42]
|||
||└─ carga útil codificada en JSON
|└─ tipo de paquete (2 => EVENT)
  • emit con binario, acknowledgement y namespace personalizado
socket.emit("test", Uint8Array.from([42]), () => {
console.log("ack recibido");
});

será codificado como:

51-/admin,13["test",{"_placeholder":true,"num":0}]
||||| || └─ carga útil codificada en JSON con placeholders para adjuntos binarios
||||| |└─ id de acknowledgement
||||| └─ separador
||||└─ namespace (no incluido cuando es el namespace principal)
|||└─ separador
||└─ número de adjuntos binarios
|└─ tipo de paquete (5 => BINARY EVENT)

y un adjunto adicional (el Uint8Array extraído)

Pros:

  • el adjunto binario se codifica en base64, así que este parser es compatible con navegadores que no soportan Arraybuffers, como IE9

Contras:

  • los paquetes con contenido binario se envían como dos frames WebSocket distintos (si la conexión WebSocket está establecida)

El parser msgpack​

Este parser usa el formato de serialización MessagePack.

El código fuente de este parser se puede encontrar aquí: https://github.com/socketio/socket.io-msgpack-parser

Uso de ejemplo:

Servidor

import { Server } from "socket.io";
import customParser from "socket.io-msgpack-parser";

const io = new Server({
parser: customParser
});

Cliente (Node.js)

import { io } from "socket.io-client";
import customParser from "socket.io-msgpack-parser";

const socket = io("https://example.com", {
parser: customParser
});

En el navegador, ahora hay un bundle oficial que incluye este parser:

CDNURL
Socket.IO CDNhttps://cdn.socket.io/4.8.3/socket.io.msgpack.min.js
cdnjshttps://cdnjs.cloudflare.com/ajax/libs/socket.io/4.8.3/socket.io.msgpack.min.js
jsDelivrhttps://cdn.jsdelivr.net/npm/socket.io-client@4.8.3/dist/socket.io.msgpack.min.js
unpkghttps://unpkg.com/socket.io-client@4.8.3/dist/socket.io.msgpack.min.js

En ese caso, no necesitas especificar la opción parser.

Pros:

  • los paquetes con contenido binario se envían como un solo frame WebSocket (si la conexión WebSocket está establecida)
  • puede resultar en cargas útiles más pequeñas (especialmente cuando se usan muchos números)

Contras:

  • incompatible con navegadores que no soportan Arraybuffers, como IE9
  • más difícil de depurar en la pestaña Network del navegador
información

Por favor ten en cuenta que socket.io-msgpack-parser se basa en la implementación de MessagePack notepack.io. Esta implementación se enfoca principalmente en el rendimiento y el tamaño mínimo del bundle, y por lo tanto no soporta características como tipos de extensión. Para un parser basado en la implementación oficial de JavaScript, por favor revisa este paquete.