JSON编码的缓冲区数据编码不正确

时间:2017-09-19 23:04:38

标签: javascript json node.js symfony websocket

我目前正在尝试json_encode一些缓冲区数据,并在node.js websocket服务器上对其进行解码失败。

我正在使用一个docker容器,它为我提供ANSI数据,我将其格式化为HTML。

我使用Symfony Process component从docker容器中获取实时进程输出,并使用socket_write将其输出到我的Node.js websocket服务器。

我将使用socket_write的docker中的数据写入Node.js服务器的代码如下所示:

$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));
});

在我的服务器上,我尝试解码json_encoded数据,如下所示:

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

此操作因语法错误而失败:

  

SyntaxError:意外的令牌{在位置66的JSON中

当我console.log我的msg服务器上的传入Node.js时,我将其作为输出:

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>)

所以似乎msg是一个缓冲流,但JSON.parse似乎对前几条消息起作用。

然后,对于我发送到我的套接字的第三条消息,它失败了。这里发生了什么?

我的缓冲区是否因为我在上一篇JSON声明中看到2个console.log个对象粘在一起而根本不知道我的消息应该被分成适当的部分?

1 个答案:

答案 0 :(得分:0)

这似乎完全解决了我的问题:

Wait for socket_write to complete before writing again

问题在于我不明白为什么。作为socket_write的第三个参数,我传递了JSON对象的长度,如下所示:

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

我知道我需要设置长度,因为它只是一个流,它接受&#34;块&#34;可以说缓冲区中的数据。

strlen($json)是不是已经解决了我的所有问题?

为什么我的socket_write消息有时仍会将多个JSON对象附加在一起?

修改

从我读过的内容开始,因为这些套接字与TCP协同工作,数据的分块似乎是因为Nagle's Algorithm而发生的,并且根据消息大小和最后一条消息被确认的时间进行分块。

PHP在PHP 7.1中引入了TCP_NODELAY,但算法是有原因的,所以你需要对此保持警惕。

我想解决这个问题的最好方法就是通过拆分你在PHP中添加的分隔符来自行拆分服务器端的消息。

纠正我,如果我错了,我很乐意听到这个想法。