我目前正在开发一个简单的NodeJS客户端,该客户端使用net类连接到PHP服务器。此外,NodeJS客户端充当Socket.IO服务器,将从PHP服务器接收的数据发送到与Socket.IO.连接的浏览器
到目前为止,一切都很顺利。然而,如果我将另一个客户端连接到Socket.IO,PHP服务器必须向每个连接的客户端发送通知。因此,它向NodeJS客户端发送一个JSON编码的数组,NodeJS客户端处理JSON数据(对其进行解码和修改)。
现在的问题是,有时PHP服务器发送的两条独立消息在NodeJS的onData事件处理函数中被连接在一起
client.on("data", function(data) {
var msgData = JSON.parse(data.toString("utf8"));
[...]
}
变量数据现在有时(不是每次!)包含两个JSON字符串,例如:
{ "todo":"message", [...] } { "todo":"message", [...] }
这当然会导致JSON.parse函数抛出异常。我预期onData函数的两个调用,变量data为:
{ "todo":"message", [...] }
在PHP服务器端,我必须迭代一个数组,该数组包含当前服务的所有Socket.IO-连接:
foreach($sockets as $id => $client) {
$nodeJS->sendData($client, array("todo" => "message", [...]);
}
$nodeJS->sendData-函数json对数组进行编码并将其发送到nodeJS客户端:
socket_write($nodeClient, json_encode($dataToSend));
$nodeJS->sendData函数被明确调用两次,就像socket_write一样。
我现在不知道是PHP还是NodeJS连接了这两个字符串。我想要的是,每次调用$NodeJS->sendData函数时,NodeJS都会调用onData处理程序一次(例如,sendData被调用两次→onData事件被激发两次)。当然,我可以在每个json编码的字符串的末尾添加一些标志,然后在onData函数中将它们拆分成一个数组。然而,我不太喜欢这种解决方案。
有没有更简单的方法来实现这一点?
重要的是要记住,当您从套接字读取数据时,数据将以任意块的形式出现,完全取决于您的代码将它们拆分为对处理有意义的单元;绝对不能保证每个块将对应于一个有意义的单元。
yannisgu已经为您提供了解决方案的第一部分(用换行符终止每个单元,这样您的代码就可以知道它的结束位置):现在您需要实现第二部分,即缓冲传入的数据并将其拆分为单元。
在初始化时,执行类似的操作
var buf = '';
并将CCD_ 1的编码设置为utf8。
在"data"
处理程序中:【更新:纳入josh3736的建议】
buf += data;
var idx;
while ((idx = buf.indexOf(''n')) >= 0) {
// there's at least one complete unit buffered up
var unit = buf.slice(0, idx);
// extract it
if (unit.slice(-1) == ''r') {
// CRLF delimited
unit = unit.slice(0, -1);
}
if (unit.length) {
// ignore empty strings
var msgData = JSON.parse(unit);
[...]
// process it
}
buf = buf.slice(idx +1);
// discard it
}
// at this point, buf is either empty or contains an incomplete
// unit which will be processed as soon as the rest of it comes in
尝试在PHP端的JSON字符串后面添加一行新行。