2014-09-12 142 views
0

我目前正在開發NodeJS中的TCP客戶端和服務器。 但是爲什麼我在這裏有一個「包丟失」? 看截圖:http://i.imgur.com/YoCtAAV.pngTCP客戶端/服務器數據包丟失

客戶端代碼:

console.log('Starting Client...') 

var net = require('net') 

var client = new net.Socket() 

client.connect(3000, '127.0.0.1', function() { 
    console.log('Connected to server on 127.0.0.1:3000') 

    var packet 
    for (i = 0; i <= 20; i++) { 
     packet = new Buffer(4) 
     packet.writeUInt32LE(i, 0) 
     client.write(packet) 

     console.log('Packet Counter sent: ' + i) 
    } 
}) 

client.on('error', function(e) { 
    if(e.code == 'ECONNRESET') { 
     console.error('Connection abnormally closed') 
    } else if(e.code == 'ECONNREFUSED') { 
     console.error('Connection refused. Server down?') 
    } else { 
     console.error('Unhandled error occured:') 
     console.error(e) 
    } 
}) 

client.on('close', function() { 
    console.log('Connection closed') 
}) 

服務器代碼:

console.log('Starting Server...') 

var net = require('net') 

var server = net.createServer(function(session) { 
    console.log('Connection opened') 

    session.on('data', function(packet) { 
     var packet_counter = packet.readUInt32LE(0) 

     console.log('Packet Counter received: ' + packet_counter) 
    }) 

    session.on('error', function(e) { 
     if(e.code == 'ECONNRESET') { 
      console.log('Connection closed') 
     } else { 
      console.error('Unhandled session error occured:') 
      console.error(e) 
     } 
    }) 

    session.on('end', function() { 
     console.log('Connection closed') 
    }) 
}) 

server.on('error', function(e) { 
    if(e.code == 'EADDRINUSE') { 
     console.error('Port 3000 already in use') 
    } else { 
     console.error('Unhandled server error occured:') 
     console.error(e) 
    } 
}) 

server.listen(3000, '0.0.0.0') 

console.log('Server started on 0.0.0.0:3000') 

如何解決這個問題,並獲得在服務器日誌中預期的輸出?

Packet Counter received: 0 
Packet Counter received: 1 
Packet Counter received: 2 
Packet Counter received: 3 
Packet Counter received: 4 
Packet Counter received: 5 
Packet Counter received: 6 
Packet Counter received: 7 
Packet Counter received: 8 
Packet Counter received: 9 
Packet Counter received: 10 
Packet Counter received: 11 
Packet Counter received: 12 
Packet Counter received: 13 
Packet Counter received: 14 
Packet Counter received: 15 
Packet Counter received: 16 
Packet Counter received: 17 
Packet Counter received: 18 
Packet Counter received: 19 
Packet Counter received: 20 

回答

0

可能沒有丟包。 TCP只是不會像你期望的那樣發送數據包。它發送一個流 - 就像一個文件。文件不是由數據包組成的,而是由字節組成的。 TCP模擬此行爲。所以當你發送兩個「數據包」時,TCP層(或者你的TCP庫,或者OS或者你的路由器或者你的ISP)可以把它們合併成一個TCP數據包,或者把它們分成多個TCP數據包。

要真正知道是否有數據包丟失,您必須檢查接收數據的總大小與發送數據的總大小。

正是人們創建更高層協議(如HTTP或FTP或Bittorrent)來編碼數據包開始和結束的位置,這是類似於文件流的行爲。

TCP不會爲你做。

+0

那麼如何分割這些組合數據包? – Dev0r 2014-09-12 16:20:00

+0

這是留給你的。 HTTP使用兩條換行符「\ n \ n」'來檢測數據包的結束(實際上是頭部,數據部分的全長以內容長度頭部作爲sring發送)。 Bittorrent使用它自己的數據編碼bencoding來定義數據開始和結束的位置。在很多協議中,傳統的方式是發送第一個字節或整數來指定數據包的大小。如果您發送的是固定大小的數據包(如整數),您可能會繼續閱讀,直到您有足夠多的字節來重建數據(保持先前不完整的讀取到臨時緩衝區中)。 – slebetman 2014-09-12 16:24:05

+0

或者您可以選擇不重新發明輪子並使用已知的工作協議(如HTTP)。 – slebetman 2014-09-12 16:26:05