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:

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.