关于下面这段代码:
Socket socket = new Socket();
socket.connect(new InetSocketAddress("localhost", 9999));
OutputStream output = socket.getOutputStream();
byte[] request = new byte[10];
for (int i = 0; i < 5; i++) {
output.write(request);
}
nagle 算法
nagle 算法讲的是减少发送端频繁的发送小包给对方。
Nagle 算法要求,当一个 TCP 连接中有在传数据(已经发出但还未确认的数据)时,小于 MSS 的报文段就不能被发送,直到所有的在传数据都收到了 ACK。同时收到 ACK 后,TCP 还不会马上就发送数据,会收集小包合并一起发送。
默认情况下 Nagle 算法都是启用的,Java 可以通过 setTcpNoDelay(true);来禁用 Nagle 算法。
一个典型的小包场景:SSH
比如登录服务器后输入ls然后换行,中间包交互的过程如下图:
Nagle 算法的意义在哪里
Nagle 算法的作用是减少小包在客户端和服务端直接传输,一个包的 TCP 头和 IP 头加起来至少都有 40 个字节,如果携带的数据比较小的话,那就非常浪费了。就好比开着一辆大货车运一箱苹果一样。
Nagle 算法是时代的产物:Nagle 算法出现的时候网络带宽都很小,当有大量小包传输时,很容易将带宽占满,出现丢包重传等现象。因此对 ssh 这种交互式的应用场景,选择开启 Nagle 算法可以使得不再那么频繁的发送小包,而是合并到一起,代价是稍微有一些延迟。现在的 ssh 客户端已经默认关闭了 Nagle 算法。