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


 

实验三的实验小结
 
在建立 TCP 连接时 , 如果第三次握手的 ACK , 服务端无法收到 , 则服务端就会短暂处于 SYN_RECV 状态 , 而客户端会处于 ESTABLISHED 状态 。
由于服务端一直收不到 TCP 第三次握手的 ACK , 则会一直重传 SYN、ACK 包 , 直到重传次数超过 tcp_synack_retries 值(默认值 5 次)后 , 服务端就会断开 TCP 连接 。
而客户端则会有两种情况:
 
  • 如果客户端没发送数据包 , 一直处于 ESTABLISHED 状态 , 然后经过 2 小时 11 分 15 秒才可以发现一个「死亡」连接 , 于是客户端连接就会断开连接 。
  • 如果客户端发送了数据包 , 一直没有收到服务端对该数据包的确认报文 , 则会一直重传该数据包 , 直到重传次数超过 tcp_retries2 值(默认值 15 次)后 , 客户端就会断开 TCP 连接 。
 
#TCP 快速建立连接
客户端在向服务端发起 HTTP GET 请求时 , 一个完整的交互过程 , 需要 2.5 个 RTT 的时延 。
由于第三次握手是可以携带数据的 , 这时如果在第三次握手发起 HTTP GET 请求 , 需要 2 个 RTT 的时延 。
但是在下一次(不是同个 TCP 连接的下一次)发起 HTTP GET 请求时 , 经历的 RTT 也是一样 , 如下图:
一文教会实战网络抓包和分析包

文章插图
 
在 Linux 3.7 内核版本中 , 提供了 TCP Fast Open 功能 , 这个功能可以减少 TCP 连接建立的时延 。
一文教会实战网络抓包和分析包

文章插图
 
 
  • 在第一次建立连接的时候 , 服务端在第二次握手产生一个 Cookie (已加密)并通过 SYN、ACK 包一起发给客户端 , 于是客户端就会缓存这个 Cookie , 所以第一次发起 HTTP Get 请求的时候 , 还是需要 2 个 RTT 的时延;
  • 在下次请求的时候 , 客户端在 SYN 包带上 Cookie 发给服务端 , 就提前可以跳过三次握手的过程 , 因为 Cookie 中维护了一些信息 , 服务端可以从 Cookie 获取 TCP 相关的信息 , 这时发起的 HTTP GET 请求就只需要 1 个 RTT 的时延;
 
注:客户端在请求并存储了 Fast Open Cookie 之后 , 可以不断重复 TCP Fast Open 直至服务器认为 Cookie 无效(通常为过期)
 
在 Linux 上如何打开 Fast Open 功能?
 
可以通过设置 net.ipv4.tcp_fastopn 内核参数 , 来打开 Fast Open 功能 。
net.ipv4.tcp_fastopn 各个值的意义:
 
  • 0 关闭
  • 1 作为客户端使用 Fast Open 功能
  • 2 作为服务端使用 Fast Open 功能
  • 3 无论作为客户端还是服务器 , 都可以使用 Fast Open 功能
TCP Fast Open 抓包分析
 
在下图 , 数据包 7 号 , 客户端发起了第二次 TCP 连接时 , SYN 包会携带 Cooike , 并且长度为 5 的数据 。
服务端收到后 , 校验 Cooike 合法 , 于是就回了 SYN、ACK 包 , 并且确认应答收到了客户端的数据包 , ACK = 5 + 1 = 6
一文教会实战网络抓包和分析包

文章插图
 
#TCP 重复确认和快速重传
当接收方收到乱序数据包时 , 会发送重复的 ACK , 以便告知发送方要重发该数据包 , 当发送方收到 3 个重复 ACK 时 , 就会触发快速重传 , 立刻重发丢失数据包 。
一文教会实战网络抓包和分析包

文章插图
 
TCP 重复确认和快速重传的一个案例 , 用 Wireshark 分析 , 显示如下:


推荐阅读