Nagle綆楁硶鐨勭珛鎰忔槸鑹ソ鐨勶紝閬垮厤緗戠粶涓厖濉炲皬灝佸寘錛屾彁楂樼綉緇滅殑鍒╃敤鐜囥備絾鏄綋Nagle綆楁硶閬囧埌delayed ACK鎮插墽灝卞彂鐢熶簡銆侱elayed ACK鐨勬湰鎰忎篃鏄負浜嗘彁楂楾CP鎬ц兘錛岃窡搴旂瓟鏁版嵁鎹庡甫涓夾CK錛屽悓鏃墮伩鍏?a >緋婃秱紿楀彛緇煎悎鐥?/a>錛屼篃鍙互涓涓猘ck紜澶氫釜孌墊潵鑺傜渷寮閿銆?br /> 鎮插墽鍙戠敓鍦ㄨ繖縐嶆儏鍐碉紝鍋囪涓绔彂閫佹暟鎹茍絳夊緟鍙︿竴绔簲絳旓紝鍗忚涓婂垎涓哄ご閮ㄥ拰鏁版嵁錛屽彂閫佺殑鏃跺欎笉騫稿湴閫夋嫨浜唚rite-write錛岀劧鍚庡啀read錛屼篃灝辨槸鍏堝彂閫佸ご閮紝鍐嶅彂閫佹暟鎹紝鏈鍚庣瓑寰呭簲絳斻傚彂閫佺鐨勪吉浠g爜鏄繖鏍?br />write(head);
write(body);
read(response);
鎺ユ敹绔殑澶勭悊浠g爜綾諱技榪欐牱錛?br />read(request);
process(request);
write(response);
榪欓噷鍋囪head鍜宐ody閮芥瘮杈冨皬錛屽綋榛樿鍚敤nagle綆楁硶錛屽茍涓旀槸絎竴嬈″彂閫佺殑鏃跺欙紝鏍規嵁nagle綆楁硶錛岀涓涓head鍙互绔嬪嵆鍙戦侊紝鍥犱負娌℃湁絳夊緟紜鐨勬錛涙帴鏀剁鏀跺埌head錛屼絾鏄寘涓嶅畬鏁達紝緇х畫絳夊緟body杈懼埌騫跺歡榪烝CK錛涘彂閫佺緇х畫鍐欏叆body錛岃繖鏃跺檔agle綆楁硶璧蜂綔鐢ㄤ簡錛屽洜涓篽ead榪樻病鏈夎ACK錛屾墍浠ody瑕佸歡榪熷彂閫併傝繖灝遍犳垚浜嗗彂閫佺鍜屾帴鏀剁閮藉湪絳夊緟瀵規柟鍙戦佹暟鎹殑鐜拌薄錛屽彂閫佺絳夊緟鎺ユ敹绔疉CK head浠ヤ究緇х畫鍙戦乥ody錛岃屾帴鏀剁鍦ㄧ瓑寰呭彂閫佹柟鍙戦乥ody騫跺歡榪烝CK錛屾偛鍓х殑鏃犱互璦璇傝繖縐嶆椂鍊欏彧鏈夌瓑寰呬竴绔秴鏃跺茍鍙戦佹暟鎹墠鑳界戶緇線涓嬭蛋銆?br />
姝e洜涓簄agle綆楁硶鍜宒elayed ack鐨勫獎鍝嶏紝鍐嶅姞涓婅繖縐峸rite-write-read鐨勭紪紼嬫柟寮忛犳垚浜嗗緢澶氱綉璐村湪璁ㄨ涓轟粈涔堣嚜宸卞啓鐨勭綉緇滅▼搴忔ц兘閭d箞宸傜劧鍚庡緢澶氫漢浼氬湪甯栧瓙閲屽緩璁鐢∟agle綆楁硶鍚э紝璁劇疆TCP_NODELAY涓簍rue鍗沖彲紱佺敤nagle綆楁硶銆備絾鏄繖鐪熺殑鏄В鍐抽棶棰樼殑鍞竴鍔炴硶鍜屾渶濂藉姙娉曞悧錛?br />
鍏跺疄闂涓嶆槸鍑哄湪nagle綆楁硶韜笂鐨勶紝闂鏄嚭鍦╳rite-write-read榪欑搴旂敤緙栫▼涓娿傜鐢╪agle綆楁硶鍙互鏆傛椂瑙e喅闂錛屼絾鏄鐢╪agle綆楁硶涔熷甫鏉ュ緢澶у潖澶勶紝緗戠粶涓厖濉炵潃灝忓皝鍖咃紝緗戠粶鐨勫埄鐢ㄧ巼涓婁笉鍘伙紝鍦ㄦ瀬绔儏鍐典笅錛屽ぇ閲忓皬灝佸寘瀵艱嚧緗戠粶鎷ュ鐢氳嚦宕╂簝銆傚洜姝わ紝鑳戒笉紱佹榪樻槸涓嶇姝㈢殑濂斤紝鍚庨潰鎴戜滑浼氳涓嬩粈涔堟儏鍐典笅鎵嶉渶瑕佺鐢╪agle綆楁硶銆傚澶у鏁板簲鐢ㄦ潵璇達紝涓鑸兘鏄繛緇殑璇鋒眰——搴旂瓟妯″瀷錛屾湁璇鋒眰鍚屾椂鏈夊簲絳旓紝閭d箞璇鋒眰鍖呯殑ACK鍏跺疄鍙互寤惰繜鍒拌窡鍝嶅簲涓璧峰彂閫侊紝鍦ㄨ繖縐嶆儏鍐典笅錛屽叾瀹炰綘鍙閬垮厤write-write-read褰㈠紡鐨勮皟鐢ㄥ氨鍙互閬垮厤寤惰繜鐜拌薄錛屽埄鐢╳ritev鍋氳仛闆嗗啓鎴栬呭皢head鍜宐ody涓璧峰啓錛岀劧鍚庡啀read錛屽彉鎴恮rite-read-write-read鐨勫艦寮忔潵璋冪敤錛屽氨鏃犻渶紱佺敤nagle綆楁硶涔熷彲浠ュ仛鍒頒笉寤惰繜銆?br />
writev鏄郴緇熻皟鐢紝鍦↗ava閲屾槸鐢ㄥ埌GatheringByteChannel.write(ByteBuffer[] srcs, int offset, int length)鏂規硶鏉ュ仛鑱氶泦鍐欍傝繖閲屽彲鑳借繕鏈変竴鐐瑰肩殑鎻愪笅錛屽緢澶氬悓瀛︾湅java nio妗嗘灦鍑犱箮閮戒笉鐢ㄨ繖涓獁ritev璋冪敤錛岃繖鏄湁鍘熷洜鐨勩備富瑕佹槸鍥犱負Java鐨剋rite鏈韓瀵笲yteBuffer鏈夊仛涓存椂緙撳瓨錛岃寃ritev娌℃湁鍋氱紦瀛橈紝瀵艱嚧嫻嬭瘯鏉ョ湅write鍙嶈屾瘮writev鏇撮珮鏁堬紝鍥犳閫氬父浼氭洿鎺ㄨ崘鐢ㄦ埛灝唄ead鍜宐ody鏀懼埌鍚屼竴涓狟uffer閲屾潵閬垮厤璋冪敤writev銆?br />
涓嬮潰鎴戜滑灝嗗仛涓疄闄呯殑浠g爜嫻嬭瘯鏉ョ粨鏉熻璁恒傝繖涓緥瀛愬緢綆鍗曪紝瀹㈡埛绔彂閫佷竴琛屾暟鎹埌鏈嶅姟鍣紝鏈嶅姟鍣ㄧ畝鍗曞湴灝嗚繖琛屾暟鎹繑鍥炪傚鎴風鍙戦佺殑鏃跺欏彲浠ラ夋嫨鍒嗕袱嬈″彂錛岃繕鏄竴嬈″彂閫併傚垎涓ゆ鍙戝氨鏄痺rite-write-read錛屼竴嬈″彂灝辨槸write-read-write-read錛屽彲浠ョ湅鐪嬩袱縐嶅艦寮忎笅寤惰繜鐨勫樊寮傘?strong>娉ㄦ剰錛屽湪windows涓婃祴璇曚笅闈㈢殑浠g爜錛屽鎴風鍜屾湇鍔″櫒蹇呴』鍒嗗湪涓ゅ彴鏈哄櫒涓婏紝浼間箮winsock瀵筶oopback榪炴帴鐨勫鐞嗕笉涓鏍楓?/strong>
鏈嶅姟鍣ㄦ簮鐮侊細
package net.fnil.nagle;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args) throws Exception {
ServerSocket serverSocket = new ServerSocket();
serverSocket.bind(new InetSocketAddress(8000));
System.out.println("Server startup at 8000");
for (;;) {
Socket socket = serverSocket.accept();
InputStream in = socket.getInputStream();
OutputStream out = socket.getOutputStream();
while (true) {
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String line = reader.readLine();
out.write((line + "\r\n").getBytes());
}
catch (Exception e) {
break;
}
}
}
}
}
鏈嶅姟绔粦瀹氬埌鏈湴8000绔彛錛屽茍鐩戝惉榪炴帴錛岃繛涓婃潵鐨勬椂鍊欏氨闃誨璇誨彇涓琛屾暟鎹紝騫跺皢鏁版嵁榪斿洖緇欏鎴風銆?br />
瀹㈡埛绔唬鐮侊細
package net.fnil.nagle;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
public class Client {
public static void main(String[] args) throws Exception {
// 鏄惁鍒嗗紑鍐檋ead鍜宐ody
boolean writeSplit = false;
String host = "localhost";
if (args.length >= 1) {
host = args[0];
}
if (args.length >= 2) {
writeSplit = Boolean.valueOf(args[1]);
}
System.out.println("WriteSplit:" + writeSplit);
Socket socket = new Socket();
socket.connect(new InetSocketAddress(host, 8000));
InputStream in = socket.getInputStream();
OutputStream out = socket.getOutputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String head = "hello ";
String body = "world\r\n";
for (int i = 0; i < 10; i++) {
long label = System.currentTimeMillis();
if (writeSplit) {
out.write(head.getBytes());
out.write(body.getBytes());
}
else {
out.write((head + body).getBytes());
}
String line = reader.readLine();
System.out.println("RTT:" + (System.currentTimeMillis() - label) + " ,receive:" + line);
}
in.close();
out.close();
socket.close();
}
}
瀹㈡埛绔氳繃涓涓獁riteSplit鍙橀噺鏉ユ帶鍒舵槸鍚﹀垎寮鍐檋ead鍜宐ody錛屽鏋滀負true錛屽垯鍏堝啓head鍐嶅啓body錛屽惁鍒欏皢head鍔犱笂body涓嬈″啓鍏ャ傚鎴風鐨勯昏緫涔熷緢綆鍗曪紝榪炰笂鏈嶅姟鍣紝鍙戦佷竴琛岋紝絳夊緟搴旂瓟騫舵墦鍗癛TT錛屽驚鐜?0嬈℃渶鍚庡叧闂繛鎺ャ?br />
棣栧厛錛屾垜浠皢writeSplit璁劇疆涓簍rue錛屼篃灝辨槸鍒嗕袱嬈″啓鍏ヤ竴琛岋紝鍦ㄦ垜鏈満嫻嬭瘯鐨勭粨鏋滐紝鎴戠殑鏈哄櫒鏄痷buntu 11.10錛?br />WriteSplit:true
RTT:8 ,receive:hello world
RTT:40 ,receive:hello world
RTT:40 ,receive:hello world
RTT:40 ,receive:hello world
RTT:39 ,receive:hello world
RTT:40 ,receive:hello world
RTT:40 ,receive:hello world
RTT:40 ,receive:hello world
RTT:40 ,receive:hello world
RTT:40 ,receive:hello world
鍙互鐪嬪埌錛屾瘡嬈¤姹傚埌搴旂瓟鐨勬椂闂撮棿闅旈兘鍦?0ms錛岄櫎浜嗙涓嬈°俵inux鐨刣elayed ack鏄?0ms錛岃屼笉鏄師鏉ヤ互涓虹殑200ms銆傜涓嬈$珛鍗矨CK錛屼技涔庤窡linux鐨剄uickack mode鏈夊叧錛岃繖閲屾垜涓嶆槸鐗瑰埆娓呮錛屾湁姣旇緝娓呮鐨勫悓瀛﹁鎸囨暀銆?br />
鎺ヤ笅鏉ワ紝鎴戜滑榪樻槸灝唚riteSplit璁劇疆涓簍rue錛屼絾鏄鎴風紱佺敤nagle綆楁硶錛屼篃灝辨槸瀹㈡埛绔唬鐮佸湪connect涔嬪墠鍔犱笂涓琛岋細
Socket socket = new Socket();
socket.setTcpNoDelay(true);
socket.connect(new InetSocketAddress(host, 8000));
鍐嶈窇涓嬫祴璇曪細
WriteSplit:true
RTT:0 ,receive:hello world
RTT:0 ,receive:hello world
RTT:0 ,receive:hello world
RTT:0 ,receive:hello world
RTT:1 ,receive:hello world
RTT:0 ,receive:hello world
RTT:0 ,receive:hello world
RTT:0 ,receive:hello world
RTT:0 ,receive:hello world
RTT:0 ,receive:hello world
榪欐椂鍊欏氨姝e父澶氫簡錛屽ぇ閮ㄥ垎RTT鏃墮棿閮藉湪1姣浠ヤ笅銆傛灉鐒剁鐢∟agle綆楁硶鍙互瑙e喅寤惰繜闂銆?br /> 濡傛灉鎴戜滑涓嶇鐢╪agle綆楁硶錛岃屽皢writeSplit璁劇疆涓篺alse錛屼篃灝辨槸灝唄ead鍜宐ody涓嬈″啓鍏ワ紝鍐嶆榪愯嫻嬭瘯錛堣鐨勫皢setTcpNoDelay榪欒鍒犻櫎錛夛細
WriteSplit:false
RTT:7 ,receive:hello world
RTT:1 ,receive:hello world
RTT:0 ,receive:hello world
RTT:0 ,receive:hello world
RTT:0 ,receive:hello world
RTT:0 ,receive:hello world
RTT:0 ,receive:hello world
RTT:0 ,receive:hello world
RTT:0 ,receive:hello world
RTT:0 ,receive:hello world
緇撴灉璺熺鐢╪agle綆楁硶鐨勬晥鏋滅被浼箋傛棦鐒惰繖鏍鳳紝鎴戜滑榪樻湁浠涔堢悊鐢變竴瀹氳紱佺敤nagle綆楁硶鍛紵閫氳繃鎴戝湪xmemcached鐨勫帇嫻嬩腑鐨勬祴璇曪紝鍚敤nagle綆楁硶鍦ㄥ皬鏁版嵁鐨勫瓨鍙栦笂鐢氳嚦鏈変竴瀹氱殑鏁堢巼浼樺娍錛宮emcached鍗忚鏈韓灝辨槸涓繛緇殑璇鋒眰搴旂瓟鐨勬ā鍨嬨備笂闈㈢殑嫻嬭瘯濡傛灉鍦╳indows涓婅窇錛屼細鍙戠幇RTT鏈澶т細鍦?00ms浠ヤ笂錛屽彲瑙亀insock鐨刣elayed ack瓚呮椂鏄?00ms銆?br />
鏈鍚庝竴涓棶棰橈紝浠涔堟儏鍐典笅鎵嶅簲璇ョ鐢╪agle綆楁硶錛熷綋浣犵殑搴旂敤涓嶆槸榪欑榪炵畫鐨勮姹?#8212;—搴旂瓟妯″瀷錛岃屾槸闇瑕佸疄鏃跺湴鍗曞悜鍙戦佸緢澶氬皬鏁版嵁鐨勬椂鍊欐垨鑰呰姹傛槸鏈夐棿闅旂殑錛屽垯搴旇紱佺敤nagle綆楁硶鏉ユ彁楂樺搷搴旀с備竴涓渶鏄庢樉鏄緥瀛愭槸telnet搴旂敤錛屼綘鎬繪槸甯屾湜鏁插叆涓琛屾暟鎹悗鑳界珛鍗沖彂閫佺粰鏈嶅姟鍣紝鐒跺悗椹笂鐪嬪埌搴旂瓟錛岃屼笉鏄鎴戣榪炵畫鏁插叆寰堝鍛戒護鎴栬呯瓑寰?00ms鎵嶈兘鐪嬪埌搴旂瓟銆?br />
涓婇潰鏄垜瀵筺agle綆楁硶鍜宒elayed ack鐨勭悊瑙e拰嫻嬭瘯錛屾湁閿欒鐨勫湴鏂硅涓嶅悵璧愭暀銆?br />
杞澆璇鋒敞鏄庡嚭澶勶細http://www.tkk7.com/killme2008/archive/2011/06/30/353441.html

]]>