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