tutorial socket nodejs example ejemplo javascript node.js websocket specifications

nodejs - websocket javascript ejemplo



Chunking WebSocket TransmisiĆ³n (2)

RFC 6455 Sección 1.1 :

Esto es lo que proporciona el protocolo [...] WebSocket: una alternativa al sondeo HTTP para la comunicación bidireccional desde una página web a un servidor remoto .

Como se dijo, los WebSockets son para las comunicaciones entre una página web y un servidor. Tenga en cuenta la diferencia entre una página web y un navegador web. Los ejemplos que se utilizan son los juegos de navegador y las aplicaciones de chat, que muestran muchos mensajes pequeños.

Si desea enviar muchos MB en un mensaje, creo que no está utilizando WebSockets de la manera en que estaban destinados. Si desea transferir archivos, hágalo utilizando una Solicitud de HTTP simple, respondida con Content-Disposition para que el navegador descargue un archivo.

Entonces, si explica por qué desea enviar una cantidad tan grande de datos, quizás alguien pueda ayudar a encontrar una solución más elegante que usar WebSockets.

Además, un cliente o servidor puede rechazar mensajes demasiado grandes (aunque no se indica explícitamente cómo se rechazará):

RFC 6455 Sección 10.4 :

Las implementaciones que tienen limitaciones específicas de la implementación y / o plataforma con respecto al tamaño del marco o al tamaño total del mensaje después del reensamblaje desde múltiples marcos DEBEN protegerse contra exceder esos límites. (Por ejemplo, un punto final malicioso puede intentar agotar la memoria de su compañero o montar un ataque de denegación de servicio enviando un único fotograma grande (por ejemplo, de tamaño 2 ** 60) o enviando una larga serie de fotogramas pequeños que son parte de un mensaje fragmentado.) Tal implementación DEBERÍA imponer un límite en los tamaños de los marcos y el tamaño total del mensaje después del reensamblaje desde múltiples marcos.

ya que estoy usando conexiones WebSocket en bases más regulares, estaba interesado en cómo funcionan las cosas bajo el capó. Así que busqué en los documentos de especificaciones interminables por un tiempo, pero hasta ahora no podía encontrar nada sobre la fragmentación de la secuencia de transmisión .

El protocolo WebSocket lo llama marcos de datos (que describe la secuencia de datos pura, por lo que también se llama marcos sin control ). Por lo que entendí la especificación, no hay una longitud máxima definida ni un valor de MTU definido (unidad de transferencia máxima), lo que a su vez significa que un único marco de datos WebSocket puede contener, por especificación (!), Una cantidad infinita de datos (Por favor corrígeme si me equivoco aquí, todavía soy un estudiante en esto).

Después de leer eso, instalé instantáneamente mi pequeño servidor Node WebSocket. Como tengo una sólida historia de Ajax (también en streaming y Comet), mis expectativas originales eran como, " debe haber algún tipo de modo interactivo para leer datos mientras se transfiere ". Pero estoy equivocado allí, ¿no?

Empecé en pequeño, con 4kb de datos.

servidor

testSocket.emit( ''data'', new Array( 4096 ).join( ''X'' ) );

y como se espera, esto llega al cliente como un solo fragmento de datos

cliente

wsInstance.onmessage = function( data ) { console.log( data.length ); // 4095 };

así que aumenté la carga útil y de hecho estaba esperando otra vez, que en algún momento, el manejador de onmessage lado del cliente disparará repetidamente, efectuando la fragmentación de la transmisión. Pero para mi sorpresa, nunca sucedió ( nodo-servidor , probado en Firefox , Chrome y Safari en el lado del cliente). Mi mayor carga útil fue 80 MB

testSocket.emit( ''data'', new Array( 1024*1024*80 ).join( ''X'' ) );

y todavía llegó en un gran pedazo de datos en el cliente. Por supuesto, esto lleva un tiempo incluso si tienes una conexión bastante buena. Las preguntas aquí son

  • ¿Hay alguna posibilidad de cortar esas secuencias, similar al modo XHR readyState3 ?
  • ¿hay algún límite de tamaño para un único marco de datos ws ?
  • ¿No se supone que los websockets transfieren cargas tan grandes? (lo que me haría preguntar de nuevo por qué no hay un tamaño máximo definido)

Todavía podría mirar desde la perspectiva equivocada en WebSockets, probablemente la necesidad de enviar grandes cantidades de datos simplemente no está allí y usted debe dividir / dividir cualquier dato lógicamente usted mismo antes de enviarlo.


En primer lugar, debe diferenciar entre el protocolo WebSocket y la API de WebSocket dentro de los navegadores .

El protocolo WebSocket tiene un límite de tamaño de fotograma de 2 ^ 63 octetos, pero un mensaje WebSocket puede estar compuesto por un número ilimitado de fotogramas.

La API de WebSocket en los navegadores no expone una API basada en marcos o en streaming, sino solo una API basada en mensajes. La carga de un mensaje entrante siempre se almacena por completo (dentro de la implementación WebSocket del navegador) antes de proporcionarla a JavaScript.

Las API de otras implementaciones de WebSocket pueden proporcionar acceso basado en trama o transmisión a la carga útil transferida a través del protocolo WebSocket. Por ejemplo, AutobahnPython sí. Puede leer más en los ejemplos aquí https://github.com/tavendo/AutobahnPython/tree/master/examples/twisted/websocket/streaming .

Divulgación: soy autor original de Autobahn y trabajo para Tavendo.

Más consideraciones:

Siempre que no haya una API frame / streaming en la API JS WebSocket del navegador, solo podrá recibir / enviar mensajes WS completos.

Una única conexión de WebSocket (simple) no puede intercalar la carga de varios mensajes. Por lo tanto, si utiliza mensajes grandes, estos se entregan en orden, y no podrá enviar mensajes pequeños mientras un gran mensaje se encuentre sobre la marcha.

Hay una próxima extensión de WebSocket (las extensiones son un mecanismo incorporado para extender el protocolo): WebSocket multiplexing. Esto permite tener múltiples conexiones WebSocket (lógicas) a través de una sola conexión TCP subyacente, lo que tiene múltiples ventajas.

Tenga en cuenta también que puede abrir múltiples conexiones WS (sobre diferentes TCP subyacentes) a un solo servidor de destino desde una sola página JS / HTML hoy .

Tenga en cuenta también: usted puede hacer "fragmentación" en la capa de aplicación: envíe sus cosas en mensajes WS más pequeños para volver a armarse.

Estoy de acuerdo, en un mundo ideal, tendrías API de mensaje / frame / streaming en el navegador más WebSocket multiplexing. Eso le daría todo el poder y la conveniencia.