关于下面这段代码:

  1. Socket socket = new Socket();
  2. socket.connect(new InetSocketAddress("localhost", 9999));
  3. OutputStream output = socket.getOutputStream();
  4. byte[] request = new byte[10];
  5. for (int i = 0; i < 5; i++) {
  6. output.write(request);
  7. }

image.png

nagle 算法

nagle 算法讲的是减少发送端频繁的发送小包给对方。

Nagle 算法要求,当一个 TCP 连接中有在传数据(已经发出但还未确认的数据)时,小于 MSS 的报文段就不能被发送,直到所有的在传数据都收到了 ACK。同时收到 ACK 后,TCP 还不会马上就发送数据,会收集小包合并一起发送。

默认情况下 Nagle 算法都是启用的,Java 可以通过 setTcpNoDelay(true);来禁用 Nagle 算法。

image.png

一个典型的小包场景:SSH

比如登录服务器后输入ls然后换行,中间包交互的过程如下图:

image.png

Nagle 算法的意义在哪里

Nagle 算法的作用是减少小包在客户端和服务端直接传输,一个包的 TCP 头和 IP 头加起来至少都有 40 个字节,如果携带的数据比较小的话,那就非常浪费了。就好比开着一辆大货车运一箱苹果一样。

image.png

Nagle 算法是时代的产物:Nagle 算法出现的时候网络带宽都很小,当有大量小包传输时,很容易将带宽占满,出现丢包重传等现象。因此对 ssh 这种交互式的应用场景,选择开启 Nagle 算法可以使得不再那么频繁的发送小包,而是合并到一起,代价是稍微有一些延迟。现在的 ssh 客户端已经默认关闭了 Nagle 算法。