Home>

I am a beginner. Let me ask you questions with inadequate knowledge. Thank you.

In Java socket communication, I want to intentionally generate a delay due to the Nagle algorithm for study and operation check.

Currently 4 bytes are sent every 1 s from the client side, and the client side transmission time and server side transmission time are viewed on the console.

If i send a small amount of data, it will enter the Nagle buffer, and I think there will be a difference of about 200ms between the sending time and the receiving time, but there is almost no time difference now.

How does the Nagle algorithm cause delays?Please professor.

Applicable source code

Server side

public class Server {
    public static ServerSocket ss = null;
    public static Socket soc = null;
    private static InputStream is = null;
    private static OutputStream os = null;
    public static void main (String [] args) {
        try {
            // create server socket
            ss = new ServerSocket (5000);
            soc = ss.accept ();
            is = soc.getInputStream ();
            Thread rcvTh = new ServerRcvThread (is);
            rcvTh.start ();
            // 10 seconds sleep
            try {
                Thread.sleep (10000);
            } catch (Exception e) {
                e.printStackTrace ();
            }
            // stop thread
            rcvTh.stop ();
        } catch (IOException e) {
            e.printStackTrace ();
        } finally {
            try {
                is.close ();
                soc.close ();
                ss.close ();
            } catch (IOException e) {
                e.printStackTrace ();
            }
        }
    }
}
class ServerRcvThread extends Thread {
    private static InputStream ins = null;
    ServerRcvThread (InputStream is) {
        this.ins = is;
    }
    public void run () {
        DateFormat format = new SimpleDateFormat ("yyyy MM dd hh: mm: ss.SSS");
        byte rcvData [] = new byte [16];
        int size = 0;
        try {
            while (true) {
                // Read data
                size = ins.read (rcvData);
                System.out.println ("size:" + size + "byte" + "Reception time =" + format.format (new Date ()));
            }
        } catch (IOException e) {
            e.printStackTrace ();
        }
    }
}

Client side

public class Client {
    private static Socket soc = null;
    private static OutputStream os = null;
    private static InputStream is = null;
    public static void main (String [] args) {
        try {
            // socket generation
            soc = new Socket ("127.0.0.1", 5000);
            soc.setTcpNoDelay (false);// Explicitly turn on the Nagle algorithm
            os = soc.getOutputStream ();
            Thread sndTh = new ClientSndThread (os);
            sndTh.start ();
            // 10 seconds sleeptry {
                Thread.sleep (10000);
            } catch (Exception e) {
                e.printStackTrace ();
            }
            // stop thread
            sndTh.stop ();
        } catch (IOException e) {
            e.printStackTrace ();
        } finally {
            try {
                is.close ();
                os.close ();
                soc.close ();
            } catch (IOException e) {
                e.printStackTrace ();
            }
        }
    }
}
class ClientSndThread extends Thread {
    private static OutputStream ous = null;
    ClientSndThread (OutputStream os) {
        this.ous = os;
    }
    public void run () {
        DateFormat format = new SimpleDateFormat ("yyyy MM dd hh: mm: ss.SSS");
        byte sndData [] = new byte [4];
        sndData [0] = 0x04;
        sndData [1] = 0x03;
        sndData [2] = 0x02;
        sndData [3] = 0x01;
        try {
            while (true) {
                // write data
                ous.write (sndData);
                ous.flush ();
                System.out.println ("Data transmission" + "Transmission time =" + format.format (new Date ()));
                // 1 second sleep
                try {
                    Thread.sleep (1000);
                } catch (Exception e) {
                    e.printStackTrace ();
                }
            }
        } catch (IOException e) {
            e.printStackTrace ();
        }
    }
}
Code modification (11.22)

Server side

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Server
{
    public static ServerSocket ss = null;
    public static Socket soc = null;
    private static InputStream is = null;
    private static OutputStream os = null;
    public static void main (String [] args)
    {
        try
        {
            // create server socket
            ss = new ServerSocket (5000);
            soc = ss.accept ();
            soc.setTcpNoDelay (true);
            is = soc.getInputStream ();
            os = soc.getOutputStream ();
            DateFormat format = new SimpleDateFormat ("yyyy MM dd hh: mm: ss.SSS");byte sndData [] = new byte [4];
            sndData [0] = 0x01;
            sndData [1] = 0x02;
            sndData [2] = 0x03;
            sndData [3] = 0x04;
            while (true)
            {
                byte rcvData [] = new byte [16];
                int size = 0;
                // Read data (wait until received)
                for (int tmp = 0;tmp<= 1;tmp ++)
                {
                    size = is.read (rcvData);
                    System.out.println ("Data reception. Size:" + size + "byte. Transmission time =" + format.format (new Date ()));
                    if (size == 8)
                    {
                        break;
                    }
                }
                // The transmission from the client is delayed by 200ms. The response is also delayed by 200ms due to the ACK delay.
                // Based on the above factors, the third and subsequent triggers
                os.write (sndData);
                os.flush ();
                System.out.println ("Data transmission" + "Transmission time =" + format.format (new Date ()));
            }
        }
        catch (IOException e)
        {
            e.printStackTrace ();
        }
        finally
        {
            try
            {
                is.close ();
                os.close ();
                soc.close ();
                ss.close ();
            }
            catch (IOException e)
            {
                e.printStackTrace ();
            }
        }
    }
}

Client side

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Client1 {
    public static void main (String [] args) {
        Thread client = new ClientThread ();
        client.start ();
        try {
            //Thread.sleep(1000);
            client.join ();
        } catch (Exception e) {
            e.printStackTrace ();
        }
    }
}
class ClientThread extends Thread {
    private static Socket soc = null;
    private static OutputStream os = null;
    private static InputStream is = null;
    public void run () {
        try {
            // socket generation
            soc = new Socket ("172.23.56.83", 5000);
            soc.setTcpNoDelay (false);
            is = soc.getInputStream ();os = soc.getOutputStream ();
            DateFormat format = new SimpleDateFormat ("yyyy MM dd hh: mm: ss.SSS");
            byte sndData [] = new byte [4];
            sndData [0] = 0x04;
            sndData [1] = 0x03;
            sndData [2] = 0x02;
            sndData [3] = 0x01;
            for (int cnt = 0;cnt<10;cnt ++) {
                // First transmission (sent immediately)
                os.write (sndData);
                os.flush ();
                System.out.println ("Data transmission" + "Transmission time =" + format.format (new Date ()));
                // 0.01 second sleep
                try {
                    Thread.sleep (10);
                } catch (Exception e) {
                    e.printStackTrace ();
                }
                // 2nd transmission (1st ACK is delayed by 200ms due to delayed ACK)
                // In addition, transmission by Nagle is also delayed by 200ms
                os.write (sndData);
                os.flush ();
                System.out.println ("Data transmission" + "Transmission time =" + format.format (new Date ()));
                byte rcvData [] = new byte [16];
                int size = 0;
                // Read data
                size = is.read (rcvData);
                System.out.println ("Data reception. Size:" + size + "byte. Transmission time =" + format.format (new Date ()));
            }
        } catch (UnknownHostException e1) {
            e1.printStackTrace ();
        } catch (IOException e1) {
            e1.printStackTrace ();
        } finally {
            try {
                is.close ();
                os.close ();
                soc.close ();
            } catch (IOException e) {
                e.printStackTrace ();
            }
        }
    }
}


Result

When Nagle is on
Receive data. Size: 4byte. Send time = 2019 11 22 01: 05: 20.537
Receive data. Size: 4byte. Transmission time = 2019 11 22 01: 05: 20.584
Data transmission Transmission time = 2019 11 22 01: 05: 20.584
Receive data. Size: 4byte. Transmission time = 2019 11 22 01: 05: 20.584
Receive data. Size: 4byte. Transmission time = 2019 11 22 01: 05: 20.631
Data transmission Transmission time = 2019 11 22 01: 05: 20.631
Receive data. Size: 4byte. Transmission time = 2019 11 22 01: 05: 20.631
Receive data. Size: 4byte. Send time = 2019 11 22 01: 05: 20.678
Data transmission Transmission time = 2019 11 22 01: 05: 20.678
Receive data. Size: 4byte. Send time = 2019 11 22 01: 05: 20.678
Receive data. Size: 4byte. Transmission time = 2019 11 22 01: 05: 20.724
...
When Nagle is off
Receive data. Size: 8byte. Transmission time = 2019 11 22 01: 22: 21.897
Data transmission Transmission time = 2019 11 22 01: 22: 21.897
Receive data. Size: 4byte. Send time = 2019 11 22 01: 22: 21.900
Receive data. Size: 4byte. Transmission time = 2019 11 22 01: 22: 21.901
Data transmission Transmission time = 2019 11 22 01: 22: 21.901
Receive data. Size: 4byte. Transmission time = 2019 11 22 01: 22: 21.901
Receive data. Size: 4byte. Transmission time = 2019 11 22 01: 22: 21.917
Data transmission Transmission time = 2019 11 22 01: 22: 21.917
...
Environment

OS: win10
JDK: 1.8
IDE: eclipse

Server and client were on the same host.

  • Answer # 1

    Simply. In socket communication that does not pass a communication line such as between the same host, the Nagle algorithm does not function because of the lower layer function than the application, so the communication line is passed.