4.22 TCP 四次挥手,可以变成三次吗?

目录

 为什么 TCP 挥手需要四次呢?

粗暴关闭 vs 优雅关闭

close函数

shotdown函数

什么情况会出现三次挥手?

什么是 TCP 延迟确认机制?

TCP 序列号和确认号是如何变化的?


在一些情况下, TCP 四次挥手是可以变成 TCP 三次挥手的4.22 TCP 四次挥手,可以变成三次吗?_第1张图片

 为什么 TCP 挥手需要四次呢?

服务器收到客户端的 FIN 报文时,内核会马上回一个 ACK 应答报文,但是服务端应用程序可能还有数据要发送,所以并不能马上发送 FIN 报文,而是将发送 FIN 报文的控制权交给服务端应用程序

是否要发送第三次挥手的控制权不在内核,而是在被动关闭方(上图的服务端)的应用程序,因为应用程序可能还有数据要发送,由应用程序决定什么时候调用关闭连接的函数,当调用了关闭连接的函数,内核就会发送 FIN 报文了,**所以服务端的 ACK 和 FIN 一般都会分开发送。 

粗暴关闭 vs 优雅关闭

close函数

同时 socket 关闭发送方向和读取方向,也就是 socket 不再有发送和接收数据的能力。

        如果有多进程/多线程共享同一个 socket,如果有一个进程调用了 close 关闭只是让 socket 引用计数 -1,并不会导致 socket 不可用,同时也不会发出 FIN 报文,其他进程还是可以正常读写该 socket,直到引用计数变为 0,才会发出 FIN 报文。


        使用close函数在TCP四次挥手的过程中,如果收到了服务端发送的数据,由于客户端已经不再具有发送和接收数据的能力,所以客户端的内核会回RST报文给服务端,然后内核会释放连接,这时就不会经历完整的 TCP 四次挥手,所以我们常说,调用 close 是粗暴的关闭4.22 TCP 四次挥手,可以变成三次吗?_第2张图片

shotdown函数

可以指定 socket 只关闭发送方向而不关闭读取方向,也就是 socket 不再有发送数据的能力,但是还是具有接收数据的能力。

        如果有多进程/多线程共享同一个 socket,shutdown 则不管引用计数,直接使得该 socket 不可用,然后发出 FIN 报文,如果有别的进程企图使用该 socket,将会受到影响。


        shutdown 函数因为可以指定只关闭发送方向而不关闭读取方向,所以即使在 TCP 四次挥手过程中,如果收到了服务端发送的数据,客户端也是可以正常读取到该数据的,然后就会经历完整的 TCP 四次挥手,所以我们常说,调用 shutdown 是优雅的关闭。 4.22 TCP 四次挥手,可以变成三次吗?_第3张图片

什么情况会出现三次挥手?

当被动关闭方(上图的服务端)在 TCP 挥手过程中,没有数据要发送」并且「开启了 TCP 延迟确认机制」,那么第二和第三次挥手就会合并传输,这样就出现了三次挥手。

然后因为 TCP 延迟确认机制是默认开启的,所以导致我们抓包时,看见三次挥手的次数比四次挥手还多。

什么是 TCP 延迟确认机制?

当发送没有携带数据的 ACK,它的网络效率也是很低的,因为它也有 40 个字节的 IP 头 和 TCP 头,但却没有携带数据报文。 为了解决 ACK 传输效率低问题,所以就衍生出了 TCP 延迟确认。 TCP 延迟确认的策略:

  • 当有响应数据要发送时,ACK 会随着响应数据一起立刻发送给对方
  • 当没有响应数据要发送时,ACK 将会延迟一段时间,以等待是否有响应数据可以一起发送
  • 如果在延迟等待发送 ACK 期间,对方的第二个数据报文又到达了,这时就会立刻发送 ACK

TCP 序列号和确认号是如何变化的?

4.22 TCP 四次挥手,可以变成三次吗?_第4张图片

4.22 TCP 四次挥手,可以变成三次吗?_第5张图片 

 

你可能感兴趣的:(小林coding,计算机网络,tcp/ip,网络,服务器)