Java Socket parameters: tcpnodelay

Source: Internet
Author: User

Tcpnodelay = false. It is also the default value to enable the Nagle algorithm. The idea of the Nagle algorithm is good. It avoids small packets in the network and improves the network utilization. But when the Nagle algorithm encounters the delayed ack tragedy. The intention of delayed Ack is to improve TCP performance. It should bring ack to the response data, and avoid confusion window syndrome. It can also identify multiple segments with one ack to save costs. The tragedy occurs in this situation. Assume that one end sends data and waits for the response from the other end. The protocol is divided into the header and data. When sending the data, the write-write option is selected unfortunately, and then read, that is, first send the header, then send the data, and finally wait for the response.
Experiment Model:
Sender (client)
Write (head );
Write (body );
Read (response );
Acceptor (server)
Read (request );
Process (request );
Write (response );
It is assumed that the head and body are relatively small. When the Nagle algorithm is enabled by default and is sent for the first time, according to the Nagle algorithm, the first segment head can be sent immediately, because there is no segment waiting for confirmation, the receiving end (server side) receives the head, but the package is incomplete, continue waiting for the body to reach and delay ack; the sending end (Client Side) continues to write to the body, at this time, the Nagle algorithm works, because the head is not ACK, so the body must be delayed. This causes the sending end (client) and the receiving end (server) to be waiting for the other side to send data:
The sender (client) waits for the acceptor ack head to continue sending the body;
The receiving end (server) is waiting for the sender to send the body and delay the Ack.
In this case, only when one end times out and data is sent can the process proceed.
Code:
Sending code

Package socket. nagle; import Java. io. *; import java.net. *; import Org. apache. log4j. logger; public class client {Private Static logger = logger. getlogger (client. class); public static void main (string [] ARGs) throws exception {// whether to separate head and bodyboolean writesp.pdf = true; string host = "localhost"; logger. debug ("writesplit:" + writesplit); Socket socket = new socket (); socket. settcpnodelay (false); socket. connect (New inetsocketaddress (host, 10000); 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 (writespill) {out. write (head. getbytes (); out. write (body. getbytes ();} else {out. write (Head + body ). getbytes ();} string line = reader. readline (); logger. debug ("RTT:" + (system. currenttimemillis ()-label) + ", receive:" + line);} In. close (); out. close (); socket. close ();}}

Acceptor code

package socket.nagle;import java.io.*;import java.net.*;import org.apache.log4j.Logger;public class Server {private static Logger logger = Logger.getLogger(Server.class);public static void main(String[] args) throws Exception {ServerSocket serverSocket = new ServerSocket();serverSocket.bind(new InetSocketAddress(10000));logger.debug(serverSocket);logger.debug("Server startup at 10000");while (true) {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();logger.debug(line);out.write((line + "\r\n").getBytes());} catch (Exception e) {break;}}}}}

Experiment results:

[test5@cent4 ~]$ java socket.nagle.Server1    [main] DEBUG socket.nagle.Server - ServerSocket[addr=0.0.0.0/0.0.0.0,port=0,localport=10000]6    [main] DEBUG socket.nagle.Server - Server startup at 100004012 [main] DEBUG socket.nagle.Server - hello world4062 [main] DEBUG socket.nagle.Server - hello world4105 [main] DEBUG socket.nagle.Server - hello world4146 [main] DEBUG socket.nagle.Server - hello world4187 [main] DEBUG socket.nagle.Server - hello world4228 [main] DEBUG socket.nagle.Server - hello world4269 [main] DEBUG socket.nagle.Server - hello world4310 [main] DEBUG socket.nagle.Server - hello world4350 [main] DEBUG socket.nagle.Server - hello world4390 [main] DEBUG socket.nagle.Server - hello world4392 [main] DEBUG socket.nagle.Server -4392 [main] DEBUG socket.nagle.Server - 

Lab 1:Enable the Nagle algorithm when writesploud = true and tcpnodelay = false

[test5@cent4 ~]$ java socket.nagle.Client0    [main] DEBUG socket.nagle.Client - WriteSplit:true52   [main] DEBUG socket.nagle.Client - RTT:12, receive: hello world95   [main] DEBUG socket.nagle.Client - RTT:42, receive: hello world137  [main] DEBUG socket.nagle.Client - RTT:41, receive: hello world178  [main] DEBUG socket.nagle.Client - RTT:41, receive: hello world218  [main] DEBUG socket.nagle.Client - RTT:40, receive: hello world259  [main] DEBUG socket.nagle.Client - RTT:40, receive: hello world300  [main] DEBUG socket.nagle.Client - RTT:41, receive: hello world341  [main] DEBUG socket.nagle.Client - RTT:41, receive: hello world382  [main] DEBUG socket.nagle.Client - RTT:41, receive: hello world422  [main] DEBUG socket.nagle.Client - RTT:40, receive: hello world

We can see that the interval between each request and the response is 40 ms, except for the first time. Linux's delayed Ack is 40 ms instead of 200 ms. The first instant ack seems to be related to the Linux quickack mode. I am not particularly clear here,
In fact, the problem lies not in the Nagle algorithm, but in the Application Programming of write-Write-read. Disabling the Nagle algorithm can solve the problem temporarily. However, disabling the Nagle algorithm also brings a lot of disadvantages. The network is filled with small packets, and the network utilization is not high. In extreme cases, A large number of small packets may cause network congestion or even crash. In this case, you only need to avoid calling in the form of write-Write-read to avoid latency. For example, the data sent in this case should not be divided into two parts.
Lab 2:Enable the Nagle algorithm when writesploud = false and tcpnodelay = false

[test5@cent4 ~]$ java socket.nagle.Client0    [main] DEBUG socket.nagle.Client - WriteSplit:false27   [main] DEBUG socket.nagle.Client - RTT:4, receive: hello world31   [main] DEBUG socket.nagle.Client - RTT:3, receive: hello world34   [main] DEBUG socket.nagle.Client - RTT:2, receive: hello world38   [main] DEBUG socket.nagle.Client - RTT:3, receive: hello world42   [main] DEBUG socket.nagle.Client - RTT:2, receive: hello world44   [main] DEBUG socket.nagle.Client - RTT:2, receive: hello world47   [main] DEBUG socket.nagle.Client - RTT:1, receive: hello world50   [main] DEBUG socket.nagle.Client - RTT:2, receive: hello world53   [main] DEBUG socket.nagle.Client - RTT:1, receive: hello world54   [main] DEBUG socket.nagle.Client - RTT:1, receive: hello world

Lab 3:Disable the Nagle algorithm when writesploud = true and tcpnodelay = true

[test5@cent4 ~]$ java socket.nagle.Client0    [main] DEBUG socket.nagle.Client - WriteSplit:true25   [main] DEBUG socket.nagle.Client - RTT:6, receive: hello world28   [main] DEBUG socket.nagle.Client - RTT:2, receive: hello world31   [main] DEBUG socket.nagle.Client - RTT:3, receive: hello world33   [main] DEBUG socket.nagle.Client - RTT:1, receive: hello world35   [main] DEBUG socket.nagle.Client - RTT:2, receive: hello world41   [main] DEBUG socket.nagle.Client - RTT:6, receive: hello world49   [main] DEBUG socket.nagle.Client - RTT:3, receive: hello world52   [main] DEBUG socket.nagle.Client - RTT:2, receive: hello world56   [main] DEBUG socket.nagle.Client - RTT:3, receive: hello world59   [main] DEBUG socket.nagle.Client - RTT:3, receive: hello world

Tutorial 4:Disable the Nagle algorithm when writesploud = false and tcpnodelay = true

[test5@cent4 ~]$ java socket.nagle.Client0    [main] DEBUG socket.nagle.Client - WriteSplit:false21   [main] DEBUG socket.nagle.Client - RTT:3, receive: hello world23   [main] DEBUG socket.nagle.Client - RTT:1, receive: hello world27   [main] DEBUG socket.nagle.Client - RTT:3, receive: hello world30   [main] DEBUG socket.nagle.Client - RTT:2, receive: hello world32   [main] DEBUG socket.nagle.Client - RTT:1, receive: hello world35   [main] DEBUG socket.nagle.Client - RTT:2, receive: hello world38   [main] DEBUG socket.nagle.Client - RTT:2, receive: hello world41   [main] DEBUG socket.nagle.Client - RTT:2, receive: hello world43   [main] DEBUG socket.nagle.Client - RTT:1, receive: hello world46   [main] DEBUG socket.nagle.Client - RTT:2, receive: hello world

No delay occurs in experiments 2 to 4.
Note:The above experiment tests the following code on Windows. The client and server must be divided into two machines. It seems that Winsock does not process loopback connections. The following is my practice: both the server and client are on a Linux machine.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.