2017-09-19 1 views
0

J'essaye actuellement de json_encode certaines données de tampon et de le décoder sur un serveur websocket node.js sans succès. J'utilise un conteneur docker qui me fournit des données ANSI que je formatte au format HTML.Les données du tampon codé JSON ne sont pas codées correctement

J'utilise le Symfony Process component pour obtenir une sortie de processus en temps réel à partir du conteneur docker et utiliser socket_write pour la sortie à mon Node.js serveur websocket.

Mon code pour écrire les données de docker avec socket_write au serveur Node.js ressemble à ceci:

$process->run(function ($type, $buffer) use ($socket, $converter) { 
    $html = $converter->convert($buffer); 

    // Pass the room we want to send the HTML socket messages to. 
    $data = [ 
     'html' => $html, 
     'room' => 'http://arbiter.dev/stephan-v/arbiter-test' 
    ]; 

    $json = json_encode($data); 

    socket_write($socket, $json, strlen($json)); 
}); 

Sur mon serveur j'essaie de décoder les json_encoded données comme ceci:

socket.on('data', (msg) => { 
    const data = JSON.parse(msg); 
    io.sockets.in(data.room).emit('log', data.html.toString().trim()); 
}); 

Cette échoue avec une erreur de syntaxe:

SyntaxError: Unexpected token { in JSON at position 66

Quand je console.log le msg entrant sur mon Node.js serveur je reçois cela comme sortie:

Websocket server online, listening on port :5600 
<Buffer 7b 22 68 74 6d 6c 22 3a 22 3c 73 70 61 6e 20 73 74 79 6c 65 3d 5c 22 62 61 63 6b 67 72 6f 75 6e 64 2d 63 6f 6c 6f 72 3a 20 23 30 37 33 36 34 32 3b 20 ... > 
<Buffer 7b 22 68 74 6d 6c 22 3a 22 3c 73 70 61 6e 20 73 74 79 6c 65 3d 5c 22 62 61 63 6b 67 72 6f 75 6e 64 2d 63 6f 6c 6f 72 3a 20 23 30 37 33 36 34 32 3b 20 ... > 
<Buffer 7b 22 68 74 6d 6c 22 3a 22 22 2c 22 72 6f 6f 6d 22 3a 22 68 74 74 70 3a 5c 2f 5c 2f 61 72 62 69 74 65 72 2e 64 65 76 5c 2f 73 74 65 70 68 61 6e 2d 76 ... > 
<Buffer 7b 22 68 74 6d 6c 22 3a 22 22 2c 22 72 6f 6f 6d 22 3a 22 68 74 74 70 3a 5c 2f 5c 2f 61 72 62 69 74 65 72 2e 64 65 76 5c 2f 73 74 65 70 68 61 6e 2d 76 ... > 
undefined:1 
{"html":"","room":"http:\/\/arbiter.dev\/stephan-v\/arbiter-test"}{"html":"","room":"http:\/\/arbiter.dev\/stephan-v\/arbiter-test"} 
                   ^

SyntaxError: Unexpected token { in JSON at position 66 
    at JSON.parse (<anonymous>) 

Il semble donc le msg est un flux tampon mais le JSON.parse semble travailler pour les deux premiers messages.

Ensuite, pour environ le troisième message que j'envoie à mon socket, il échoue. Qu'est-ce qui se passe ici?

Est-ce que mon tampon ne sait tout simplement pas que mes messages doivent être regroupés en morceaux, puisque je vois 2 JSON objets collés ensemble sur ma dernière déclaration console.log?

+0

Avec la mise en réseau, vous ne pouvez jamais dépendre de la façon dont les données sont tronquées. C'est pourquoi la plupart des protocoles ont un indicateur de longueur, donc il sait combien d'octets sont nécessaires pour terminer ce message, et ensuite prêt pour le prochain. – Keith

+0

Comment est-ce un problème 'websocket'? Utilisez-vous TCP/IP brut ou le protocole Websocket? Deux choses différentes. – Myst

+0

Mon 'socket_write' est une longueur de chaîne comme un troisième argument comme ça:' strlen ($ json) 'est-ce là où ça va mal alors? Peut-il ne pas calculer la bonne longueur ou est-ce que je dépasse la limite ou quelque chose? –

Répondre

0

Cela semble avoir résolu mon problème complètement:

Wait for socket_write to complete before writing again

Le problème est que je ne comprends pas pourquoi. Comme mon troisième argument pour socket_write je passe dans la longueur de mon objet JSON comme ceci:

socket_write($socket, $json, strlen($json)); 

Je sais que je dois définir une longueur parce qu'il est tout simplement un flux et il accepte « morceaux » de données dans la mémoire tampon pour ainsi dire.

Mais le strlen($json) ne devrait-il pas déjà résoudre tous mes problèmes?

Pourquoi mes messages socket_write ajoutent-ils parfois plusieurs objets JSON ensemble?

Modifier

D'après ce que je lis depuis ces prises avec TCP l'Chunking des données semble se produire en raison de Nagle's Algorithm et sont divisés en séquences selon la taille du message et lorsque le dernier message a été reconnu. PHP a introduit un TCP_NODELAY en PHP 7.1 mais l'algorithme est là pour une raison donc vous devez vous méfier de cela.

Je suppose que la meilleure façon de résoudre ce problème consiste simplement à scinder le message du côté serveur en séparant un délimiteur que vous avez ajouté en PHP.

Corriger mon erreur si je me trompe, j'aimerais avoir des commentaires à ce sujet.