3

我想测量通过 tcp 连接发送 x 数量的 pkts 和 n 字节所需的时间。唯一的问题是我的数据包正在合并。我知道 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);
4

1 回答 1

7

setNoDelay通过设置为 true ,您已经在代码中禁用了 Nagle 算法。你面临的问题是不同的。您面临的问题是 TCP 协议没有数据包的概念。

底层协议 IP 处理数据包。TCP 是在 IP 之上实现的更高级别的基于流的协议,它允许软件假装它正在读取和写入文件描述符。因此,隐含在 TCP 协议设计的意图中,它忽略了数据包边界并将所有消息合并到单个流中。

请注意,您的问题不仅在于合并小消息,还在于拆分大消息。它可能发生在传输端,可能发生在接收端,甚至可能发生在路由器和代理中。您实际上无法控制 TCP 消息在何处拆分和合并。

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

HTTP 1.0 和更早的版本实现了一个非常简单的条件来表示数据包的结束:只需关闭连接。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

或者您也可以借鉴 HTTP 使用换行符作为分隔符的想法。这样做的好处是该协议更容易在 javascript 中处理,因为它主要是基于文本的:

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

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

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

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

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

于 2012-11-20T05:07:33.480 回答