2012-11-19 6 views
2

TCP 연결을 통해 n 개의 바이트로 pkts 양을 보내는 데 걸리는 시간을 측정하고 싶습니다. 유일한 문제는 내 패킷이 병합되는 것입니다. TCP가 기본적으로이 작업을 수행한다는 것을 알고 있지만 패킷을 병합하는 경우에도 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'); 
}); 

서버 : 이미 true로 setNoDelay를 설정하여 코드에서 Nagle 알고리즘을 비활성화 한

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

. 당신이 직면하고있는 문제는 다릅니다. 직면 한 문제는 TCP 프로토콜에 패킷 개념이 없다는 것입니다.

기본 프로토콜 인 IP는 패킷을 처리합니다. TCP는 IP 위에 구현 된 상위 레벨 스트림 기반 프로토콜로, 소프트웨어가 파일 설명자를 읽고 쓰는 척하는 역할을합니다. 따라서 TCP 프로토콜 설계의 의도에 내재되어 있으므로 패킷 경계를 무시하고 모든 메시지를 단일 스트림으로 병합합니다.

작은 메시지를 병합하는 것뿐만 아니라 큰 메시지를 분할하는 것 또한 문제가된다는 점에 유의하십시오. 그것은 전송시 발생할 수 있습니다, 그것은 수신 엔드에서 발생할 수 있습니다, 심지어 라우터와 프록시에서 일어날 수 있습니다. TCP 메시지가 분할되고 병합되는 위치를 실제로 제어 할 수는 없습니다.

메시지가 끝나는 정확한 위치를 알고 싶다면 TCP 위에 다른 프로토콜을 사용해야합니다. 하나의 간단한 예가 HTTP입니다.

HTTP 1.0 및 이전 버전은 패킷의 끝을 알리는 아주 간단한 조건을 구현합니다. 간단히 연결을 닫습니다. Content-Length 헤더를 추가하여 개선

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하십시오 HTTP 1.0 패킷은 다음 구조를 갖는다. 이렇게하면 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가하는대로 구분 기호로 줄 바꿈을 사용하는 아이디어를 빌릴 수 있습니다. 데이터가 다음 줄 바꿈을 포함해야하는 경우

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. 따라서 바퀴를 다시 발명 할 필요가 없습니다.노드에도 HTTP가 내장되어 있습니다. HTTP 용도로는 머리말에 수백 바이트의 오버 헤드를 추가하여 설명하기가 어렵습니다. 낮은 오버 헤드 프로토콜을 원할 경우 항상 FTP가 있습니다. 그리고 npm에는 몇 가지 구현이 있습니다.