Node.js | 禁用naglealgorithm

我想测量通过tcp连接发送x个字节数量的pkts所花费的时间。 唯一的问题是我的数据包正在合并。 我知道TCP默认是这样做的,但是我怎样才能让它立即发送,甚至合并数据包。

客户:

var net = require('net'); var HOST = '127.0.0.1'; var PORT = 6969; var number_packets = 2500; var packet_size = 200; var client = new net.Socket(); client.connect(PORT, HOST, function() { client.setNoDelay(true); for (var i = 0; i <= 100; i++) { var message = new Buffer(packet_size); console.log('Sending message #: '+i); client.write(message); } }); client.on('data', function(data) { console.log('DATA: ' + data); // Close the client socket completely client.destroy(); }); client.on('close', function() { console.log('Connection closed'); }); 

服务器:

 var net = require('net'); var HOST = '127.0.0.1'; var PORT = 6969; var count = 1; net.createServer(function(sock) { sock.on('data', function(data) { var size = data.length; console.log('pkt: '+count+' size: '+size); //sock.write(data+'-'); count++; }); sock.on('close', function(data) { console.log('CLOSED: ' + sock.remoteAddress +' '+ sock.remotePort); }); }).listen(PORT, HOST); //console.log('Server listening on ' + HOST +':'+ PORT); 

您已经通过将setNoDelay设置为true来禁用代码中的Naglealgorithm。 你面临的问题是不同的。 你面临的问题是TCP协议没有包的概念。

底层协议IP处理数据包。 TCP是基于IP的高层stream协议,允许软件假装读写文件描述符。 因此,隐含在TCP协议devise的意图中,它忽略了数据包边界,并将所有消息合并成一个单一的数据stream。

请注意,您的问题不仅在于合并小消息,而且还在于分割大消息。 它可能发生在传输上,可能发生在接收端,甚至可能发生在路由器和代理服务器上。 TCP消息被拆分和合并的位置并不是真正的控制。

如果你想知道你的消息到底在哪里,你需要在TCP之上使用另一个协议。 一个简单的例子是HTTP:

HTTP 1.0和更早的版本实现了一个非常简单的条件来表示数据包的结束:只需closures连接即可。 HTTP 1.0数据包具有以下结构:

 HTTP/version status (200 for OK) comment (human readable meaning of status code) headers (note, commands and headers are separated by newlines (\n)) headers headers two newlines (\n) indicates end of headers: data data data connection closed indicating end of data 

HTTP 1.1通过添加Content-Length头来改进了这一点。 这允许HTTP 1.1每个连接发送多个“数据包”(html文件,gif图像等)。 所以HTTP 1.1看起来像这样:

 HTTP/version status comment headers Content-length: number of bytes in the data section headers data data end of data HTTP/version status comment (beginning of second packet) headers Content-length: number of bytes in the data section headers data data end of data 

现在这是在TCP之上运行的最简单的协议之一。 但内容长度的概念来自更老的协议。 IP本身有一个长度字段。 以太网帧也是如此。 您可以使用相同的想法为您的任务实现一个简单的协议:

 [ len ][ len ][ data ][ data ][ data ] ... \________/ \____________________/ | | | | | "length" bytes of data | two bytes indicating length of packet 

或者你也可以借用使用换行符作为分隔符的想法。 这有一个好处,协议更容易处理在JavaScript中,因为它主要是基于文本:

 data data data data data data\n \___________________/ | | | | end of packet | data section (must not contain newlines) 

如果数据必须包含换行符,那么你可以用它在JSON中处理的方式来处理它:发送“\”后跟“n”(即实现“\ n”转义序列)。 请注意,您可以select任何内容作为分隔符,而不必是换行符。

你甚至可以混合概念。 这是我几年前开发的基于文本的协议,但使用二进制协议的长度前缀思想:

 12345;data data data data ... | | | |____ semicolon indicates start of data section | | length of data section sent as an ASCII string 

当然,最好的方法是使用其他人已经在node.js中发明和实现的协议。 这可以帮助您避免重蹈覆辙。 节点甚至有内置的HTTP。虽然我明白,为了您的目的,HTTP在标头中增加了几百个字节的开销,这是难以解释的。 如果你想要一个低开销的协议,总是有FTP。 在npm上有几个实现。