2012-11-19 40 views
2

我想測量通過tcp連接發送x個字節數的pkts所需的時間。唯一的問題是我的數據包正在合併。我知道TCP默認是這樣做的,但是我怎麼讓它立即發送它們甚至合併數據包。Node.js |禁用nagle算法

客戶:

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

你已經在你的代碼通過設置setNoDelay爲真已被禁用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 

最好的辦法,當然是使用別人已經發明並在節點實現的協議.js文件。這可以幫助您避免重蹈覆轍。Node甚至內置了HTTP。儘管我明白,爲了您的目的,HTTP會在標頭中增加數百個字節的開銷,但難以說明問題。如果你想要一個低開銷協議,總是有FTP。在npm上有幾個實現。