Node.js中面向行的流

时间:2011-07-04 16:05:53

标签: javascript node.js io stream buffer

我正在使用Node.js开发一个多进程应用程序。在此应用程序中,父进程将生成子进程并使用基于JSON的消息传递协议通过管道与其进行通信。我发现大型JSON消息可能会被“切断”,因此发送到管道上的数据侦听器的单个“块”不包含完整的JSON消息。此外,小JSON消息可以分组在同一块中。每个JSON消息都将由换行符分隔,因此我想知道是否已有一个实用程序将缓冲管道读取流,以便它一次发出一行(因此,对于我的应用程序,一个JSON文档)在一个时间)。这似乎是一个非常常见的用例,所以我想知道它是否已经完成。

我很感激任何人都可以提供任何指导。感谢。

4 个答案:

答案 0 :(得分:4)

也许佩德罗的carrier可以帮到你?

  

Carrier可帮助您实施新线路   通过node.js终止协议。

     

客户端可以发送给你的块   线路和承运人只会通知您   在每条完成的线上。

答案 1 :(得分:2)

我对此问题的解决方案是发送每个以特殊unicode字符终止的JSON消息。您通常不会在JSON字符串中获得的字符。称之为TERM。

所以发件人只做“JSON.stringify(message)+ TERM;”写下来。 接收器然后在TERM上拆分数据并使用JSON.parse()解析部件,这非常快。 诀窍是最后一条消息可能无法解析,因此我们只需保存该片段并将其添加到下一条消息的开头。接收代码如下:

        s.on("data", function (data) {
        var info = data.toString().split(TERM);
        info[0] = fragment + info[0];
        fragment = '';

        for ( var index = 0; index < info.length; index++) {
            if (info[index]) {
                try {
                    var message = JSON.parse(info[index]);
                    self.emit('message', message);
                } catch (error) {
                    fragment = info[index];
                    continue;
                }
            }
        }
    });

其中“fragment”被定义为在数据块之间存在的地方。

但是什么是TERM?我使用了unicode替换字符'\ uFFFD'。也可以使用twitter使用的技术,其中消息由'\ r \ n'分隔,推文使用'\ n'表示新行,并且从不包含'\ r \ n'

我觉得这比包括长度之类的东西要简单得多。

答案 2 :(得分:1)

最简单的解决方案是在每条消息之前将json数据的长度发送为固定长度前缀(4个字节?),并使用一个简单的非成帧解析器来缓冲小块或拆分较大的块。

您可以尝试node-binary以避免手动编写解析器。查看scan(key, buffer)文档示例 - 它完全按行读取。

答案 3 :(得分:0)

只要换行符(或您使用的任何分隔符)只会分隔JSON消息而不是嵌入它们,您可以使用以下模式:

const buf = ''
s.on('data', data => {
  buf += data.toString()
  const idx = buf.indexOf('\n')
  if (idx < 0) { return } // No '\n', no full message
  let lines = buf.split('\n')
  buf = lines.pop() // if ends in '\n' then buf will be empty
  for (let line of lines) {
    // Handle the line
  }
})