tutorial socket nodejs example javascript json node.js websocket stream

nodejs - websocket javascript



¿Cómo manejar mensajes websocket extrañamente combinados? (5)

Como leí su pregunta muchas veces, y probé y emulé su problema, le sugiero que primero haga una docker . Debido a que con una imagen de la docker dos, usted y yo podemos tener un área coherente que cuando Websocket envía un mensaje, tanto usted como yo obtenemos una base de datos consistente.

Aquí, en mi computadora, intenté muchas veces hacer que mi sistema actuara como el tuyo, pero falla en cada intento.

En realidad, cuando accede a rawdata en la this.ws.on llamada this.ws.on , es muy tarde para arreglar algo. Debes configurar tu servidor para pasar los caracteres codificados correctos. Cada acción en rawdata causa la pérdida de datos para su aplicación. De hecho, su servidor debería pasar los datos correctos, y es muy extraño para mí, la node ws library usa de forma predeterminada los caracteres utf8 . Tal vez, los caracteres que se construyeron en su servidor están en otra codificación de texto, pero en serio le sugiero que lea esta pregunta y este artículo de medio . Estos enlaces pueden ayudarlo a escribir su servidor con una configuración que pasa datos de string codificación de texto utf8 .

Debe establecer una condición if para pasar utf8 los datos de la cadena utf8 .

Actualizar

Mi respuesta a esta pregunta es una forma muy general de depurar el problema, pero al final, el PostOwner comentó bajo mi respuesta que el problema se estaba produciendo debido a su código de cliente que hace que la CPU spike y los resultados de WS muestran deformados.

Me estoy conectando a una api de websocket externa utilizando la biblioteca ws node (nodo 10.8.0 en Ubuntu 16.04). Tengo un oyente que simplemente analiza el json y lo pasa a la devolución de llamada:

this.ws.on(''message'', (rawdata) => { let data = null; try { data = JSON.parse(rawdata); } catch (e) { console.log(''Failed parsing the following string as json: '' + rawdata); return; } mycallback(data); });

Ahora recibo errores en los que el rawData tiene el siguiente aspecto ( rawData contenidos irrelevantes):

�~A { "id": 1, etc.. }�~� { "id": 2, etc..

Entonces me pregunté; que son estos personajes Al ver la estructura, inicialmente pensé que el primer signo extraño debe ser un corchete de apertura de una matriz ( [ ) y el segundo una coma ( , ) para que cree una matriz de objetos.

Luego investigué el problema aún más al escribir los rawdata en rawdata en un archivo cada vez que encuentra un error de análisis JSON. En aproximadamente una hora, se han guardado alrededor de 1500 de estos archivos de error, lo que significa que esto sucede mucho . He cat un par de estos archivos en el terminal, de los cuales subí un ejemplo a continuación:

Algunas cosas son interesantes aquí:

  1. Los archivos siempre comienzan con uno de estos signos extraños.
  2. Los archivos parecen existir de varios mensajes que deberían haberse recibido por separado. Los signos extraños separan esos mensajes individuales.
  3. Los archivos siempre terminan con un objeto json sin terminar.
  4. Los archivos son de diferentes longitudes. No siempre son del mismo tamaño y, por lo tanto, no se cortan en una longitud específica.

No tengo mucha experiencia con los websockets, pero ¿podría ser que mi websocket de alguna manera reciba un flujo de mensajes que concatene, con estos signos extraños como separadores, y luego corte el último mensaje al azar? Tal vez porque estoy recibiendo un flujo constante de mensajes muy rápido?

¿O podría ser debido a un error (o funcionalidad) del servidor en el que combina esos mensajes individuales?

¿Alguien sabe lo que está pasando aquí? Todos los consejos son bienvenidos!

[EDITAR]

@bendataclear sugirió interpretarlo como utf8. Así lo hice, y pegué una captura de pantalla de los resultados a continuación. La primera impresión es como es, y la segunda se interpreta como utf8. Para mí esto no se parece en nada. Por supuesto, podría convertir a utf8 y luego dividirme por esos caracteres. Aunque el último mensaje siempre está cortado, al menos esto haría que algunos de los mensajes sean legibles. Sin embargo, otras ideas todavía son bienvenidas.


El problema que tiene es que un lado envía un JSON con una codificación diferente, mientras que el otro lado lo interpreta.

Intenta resolver este problema con el siguiente código:

const { StringDecoder } = require(''string_decoder''); this.ws.on(''message'', (rawdata) => { const decoder = new StringDecoder(''utf8''); const buffer = new Buffer(rawdata); console.log(decoder.write(buffer)); });

O con utf16 :

const { StringDecoder } = require(''string_decoder''); this.ws.on(''message'', (rawdata) => { const decoder = new StringDecoder(''utf16''); const buffer = new Buffer(rawdata); console.log(decoder.write(buffer)); });

Por favor, lea: String Decoder Documentation


Esos caracteres se conocen como "CARÁCTER DE REEMPLAZO": se usan para reemplazar un carácter desconocido, no reconocido o no representable.

De: https://en.wikipedia.org/wiki/Specials_(Unicode_block)

El carácter de reemplazo (a menudo un diamante negro con un signo de interrogación blanco o una caja cuadrada vacía) es un símbolo que se encuentra en el estándar de Unicode en el punto de código U + FFFD en la tabla de Especiales. Se utiliza para indicar problemas cuando un sistema no puede representar un flujo de datos a un símbolo correcto. Normalmente se ve cuando los datos no son válidos y no coinciden con ningún carácter

Comprobando la sección 8 del manejo de errores del protocolo WebSocket :

8.1. Manejo de errores en UTF-8 desde el servidor

Cuando un cliente debe interpretar un flujo de bytes como UTF-8 pero encuentra que el flujo de bytes no es en realidad un flujo de UTF-8 válido, entonces cualquier byte o secuencia de bytes que no sean secuencias de UTF-8 válidas DEBE interpretarse como un U + FFFD CARÁCTER DE SUSTITUCIÓN.

8.2. Manejo de errores en UTF-8 desde el cliente

Cuando un servidor debe interpretar un flujo de bytes como UTF-8 pero encuentra que el flujo de bytes no es en realidad un flujo de UTF-8 válido, el comportamiento no está definido. Un servidor podría cerrar la conexión, convertir secuencias de bytes no válidas en CARACTERES DE REEMPLAZO DE U + FFFD, almacenar los datos de forma literal o realizar un procesamiento específico de la aplicación. Los subprotocols en capas en el protocolo WebSocket pueden definir un comportamiento específico para los servidores.

Depende de la implementación o la biblioteca en uso cómo lidiar con esto, por ejemplo, de este post Implementación de servidores Web Socket con Node.js :

socket.ondata = function(d, start, end) { //var data = d.toString(''utf8'', start, end); var original_data = d.toString(''utf8'', start, end); var data = original_data.split(''/ufffd'')[0].slice(1); if (data == "kill") { socket.end(); } else { sys.puts(data); socket.write("/u0000", "binary"); socket.write(data, "utf8"); socket.write("/uffff", "binary"); } };

En este caso, si se encuentra un hará:

var data = original_data.split(''/ufffd'')[0].slice(1); if (data == "kill") { socket.end(); }

Otra cosa que podrías hacer es actualizar el nodo al último establo, a partir de este post OpenSSL y Rompiendo el cambio de UTF-8 (corregido en el Nodo v0.8.27 y v0.10.29) :

A partir de estas versiones, si intenta pasar una cadena con un par de sustitutos no coincidentes, Node reemplazará ese carácter con el carácter Unicode desconocido (U + FFFD). Para preservar el comportamiento anterior, establezca la variable de entorno NODE_INVALID_UTF8 en cualquier cosa (incluso en nada). Si la variable de entorno está presente, volverá al comportamiento anterior.



Supongo que está trabajando solo con caracteres en inglés / ASCII y algo probablemente afectó la secuencia. ( NOTA : Supongo que) , no hay caracteres especiales, si es así, te sugeriré que pases toda la cadena json a esta función:

function cleanString(input) { var output = ""; for (var i=0; i<input.length; i++) { if (input.charCodeAt(i) <= 127) { output += input.charAt(i); } } console.log(output); } //example cleanString("�~�")

Puede hacer referencia a ¿Cómo eliminar caracteres UTF-8 no válidos de una cadena de JavaScript?

EDITAR

De un artículo de Internet Engineering Task Force (IETF) ,

Una clase común de problemas de seguridad surge cuando se envían datos de texto usando la codificación incorrecta. Este protocolo especifica que los mensajes con un tipo de datos de texto (a diferencia de los tipos binarios u otros) contienen datos codificados en UTF-8. Aunque aún se indica la longitud y las aplicaciones que implementan este protocolo deben usar la longitud para determinar dónde termina realmente el marco, enviar datos de forma incorrecta

Los "datos de carga útil" son datos de texto codificados como UTF-8. Tenga en cuenta que un marco de texto en particular puede incluir una secuencia parcial de UTF-8; sin embargo, el mensaje completo DEBE contener UTF-8 válido. UTF-8 no válido en mensajes reensamblados se maneja como se describe en Manejo de errores en datos codificados en UTF-8 , que establece que cuando un punto final debe interpretar un flujo de bytes como UTF-8 pero encuentra que el flujo de bytes no es, de hecho, una secuencia UTF-8 válida, ese punto final DEBE _Fail la conexión WebSocket_. Esta regla se aplica tanto durante el saludo de apertura como durante el intercambio de datos posterior.

Realmente creo que su error (o funcionalidad) proviene del lado del servidor que combina sus mensajes individuales, por lo que sugeriré una lógica para asegurar que todos sus caracteres DEBEN convertirse de Unicode a ASCII codificando primero los caracteres como UTF-8. Y es posible que también desee instalar npm install --save-optional utf-8-validate para verificar de manera eficiente si un mensaje contiene UTF-8 válido como lo requiere la especificación.

Es posible que también desee aprobar una condición if para ayudarlo a realizar algunas comprobaciones;

this.ws.on(''message'', (rawdata) => { if (message.type === ''utf8'') { // accept only text }

Espero que esto ayude.