我有一个更大的缓冲区,我正在尝试将其作为数据包发送。 Nodejs 将缓冲区分割成更小的(65k 数据包)。一旦客户端收到它们,我如何确保数据包组合在一起并有效地将它们重新组合到缓冲区中?

几乎用这个作为测试:

// tcp socket 
var buf = Buffer.alloc(265000); 
socket.write(buf); 

然后在客户端,我需要以某种方式将 65k 数据包组合回缓冲区。

谢谢

请您参考如下方法:

TCP 可以自由地将线路上的数据分解成任意大小的数据包。根据不同的实现或物理传输,大小可以不同。您无法确切知道这将如何发生,也不应该具体取决于它是如何实现的。它甚至可能会根据您的数据采用的路径而有所不同。

此外,.on('data', ...) 事件只是为您提供到目前为止已到达的所有数据。虽然数据包的顺序得到保证,但不能保证如果您写入一组特定的字节,它们都会在同一个 data 事件中到达。它们可以被分解成更小的碎片,并且可能以更小的碎片形式到达。当 TCP 之上没有真正的协议(protocol)时,这就是 TCP 较低级别上发生的情况。

因此,如果您通过 TCP 发送大量数据,则必须发明自己的协议(protocol)才能知道何时获得整组数据。有多种不同的方案可以实现此目的。

  1. 分隔符。某种分隔符,不会出现在实际数据中,表示一组数据的结束。您读取并解析数据,直到获得分隔符,然后您就知道您拥有可以处理的完整数据集。 HTTP 协议(protocol)使用换行符作为分隔符。有时使用零字节作为分隔符。

  2. 先发送长度。对于二进制数据,通常先发送数据的长度,然后接收者知道他们正在读取多少字节的数据,直到获得完整的数据集.

  3. 现有协议(protocol)。像 webSocket 协议(protocol)这样的协议(protocol)可以让您发送任意大小的消息,它会自动将它们包装成包含长度信息的数据包,以便可以自动为您重新组合它们到原始数据集,而无需您自己执行此操作。还有数千种其他协议(protocol),其中一种可能非常适合您的需求,您只需使用现有的实现即可,而无需编写自己的实现。

如果您有某种机制知道何时收到一组完整的数据,那么您可以设置 data 事件处理程序来读取数据,将其收集到缓冲区中并观察结束数据(使用您选择的任何机制)。当您看到一组末尾时,您可以将其与可能在其之后到达的任何其他数据分开,然后对其进行处理。

<小时 />

因此,假设您使用零字节作为分隔符,并且您已确保零不能也不会出现在实际数据中。然后,您将设置一个数据处理程序,如下所示:

let accumulatedData = Buffer.alloc(0); 
socket.on('data', data => { 
    // check for delimiter character 
    let offset = data.indexOf(0); 
    if (offset !== -1) { 
        // get the whole message into one Buffer 
        let msg = Buffer.concat(accumulatedData, data.slice(0, offset)); 
 
        // put rest of data into the accumulatedData buffer as part of next piece of data 
        // skip past the delimiter 
        accumulatedData = data.slice(offset + 1); 
 
        // emit that we now have a whole msg 
        socket.emit('_msg', msg); 
 
    } else { 
        // no delimiter yet, just accumulate the data 
        accumulatedData = Buffer.concat(accumulatedData, data); 
    } 
}); 
 
// if any accumulated data still here at end of socket 
// notify about it 
// this is optional as it may be a partial piece of data (no delimiter) 
socket.on('end', () => { 
   if (accumulatedData.length) { 
       socket.emit('_msg', accumulatedData); 
   } 
}); 
 
// this is my own event which is emitted when a whole message is available 
// for processing 
socket.on('_msg', msg => { 
   // code here to process whole msg 
}); 

注意:此实现删除了消息末尾的分隔符


评论关闭
IT源码网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!