一文教会实战网络抓包和分析包(11)


使用 Nagle 算法 , 该算法的思路是延时处理 , 只有满足下面两个条件中的任意一个条件 , 才能可以发送数据:
 

  • 条件一:要等到窗口大小 >= MSS 并且 数据大小 >= MSS;
  • 条件二:收到之前发送数据的 ack 回包;
 
只要上面两个条件都不满足 , 发送方一直在囤积数据 , 直到满足上面的发送条件 。
一文教会实战网络抓包和分析包

文章插图
 
上图右侧启用了 Nagle 算法 , 它的发送数据的过程:
 
  • 一开始由于没有已发送未确认的报文 , 所以就立刻发了 H 字符;
  • 接着 , 在还没收到对 H 字符的确认报文时 , 发送方就一直在囤积数据 , 直到收到了确认报文后 , 此时没有已发送未确认的报文 , 于是就把囤积后的 ELL 字符一起发给了接收方;
  • 待收到对 ELL 字符的确认报文后 , 于是把最后一个 O 字符发送了出去
 
可以看出 , Nagle 算法一定会有一个小报文 , 也就是在最开始的时候 。
另外 , Nagle 算法默认是打开的 , 如果对于一些需要小数据包交互的场景的程序 , 比如 , telnet 或 ssh 这样的交互性比较强的程序 , 则需要关闭 Nagle 算法 。
可以在 Socket 设置 TCP_NODELAY 选项来关闭这个算法(关闭 Nagle 算法没有全局参数 , 需要根据每个应用自己的特点来关闭) 。
一文教会实战网络抓包和分析包

文章插图
 
 
那延迟确认又是什么?
 
事实上当没有携带数据的 ACK , 它的网络效率也是很低的 , 因为它也有 40 个字节的 IP 头 和 TCP 头 , 但却没有携带数据报文 。
为了解决 ACK 传输效率低问题 , 所以就衍生出了TCP 延迟确认 。
TCP 延迟确认的策略:
 
  • 当有响应数据要发送时 , ACK 会随着响应数据一起立刻发送给对方
  • 当没有响应数据要发送时 , ACK 将会延迟一段时间 , 以等待是否有响应数据可以一起发送
  • 如果在延迟等待发送 ACK 期间 , 对方的第二个数据报文又到达了 , 这时就会立刻发送 ACK
 
一文教会实战网络抓包和分析包

文章插图
 
延迟等待的时间是在 Linux 内核中定义的 , 如下图:
一文教会实战网络抓包和分析包

文章插图
 
关键就需要 HZ 这个数值大小 , HZ 是跟系统的时钟频率有关 , 每个操作系统都不一样 , 在我的 Linux 系统中 HZ 大小是 1000 , 如下图:
一文教会实战网络抓包和分析包

文章插图
 
知道了 HZ 的大小 , 那么就可以算出:
 
  • 最大延迟确认时间是 200 ms (1000/5)
  • 最短延迟确认时间是 40 ms (1000/25)
 
TCP 延迟确认可以在 Socket 设置 TCP_QUICKACK 选项来关闭这个算法 。
一文教会实战网络抓包和分析包

文章插图
 
 
延迟确认 和 Nagle 算法混合使用时 , 会产生新的问题
 
当 TCP 延迟确认 和 Nagle 算法混合使用时 , 会导致时耗增长 , 如下图:
一文教会实战网络抓包和分析包


推荐阅读