本次讨论以下三点:
1、 fin拆链为啥4次握手,而syn建链只需要3次
2、 四次握手中,tcp协议栈和应用程序都做了什么?
3、 半关闭、同时关闭。
Fin拆链需要4次握手,如下图:
Fin拆链为啥需要四次握手
讨论fin为啥4次握手,这个要把tcp协议栈和应用程序结合起来看,下图是fin拆链过程应用程序的动作。
Fin报文是由自己的应用层进行“写操作close”动作触发的,而不是tcp协议栈自发的发送fin报文。
比如上图,当服务器B收到对方的Fin报文,仅仅意味着服务器A的应用不再发送数据(应用程序的写操作close),但是并不意味着服务器B的应用也不发送数据了。
Tcp收到fin后,给应用程序发送EOF(end of file),并响应ack。服务器B的应用程序也写close,tcp再发送fin。
Fin报文的响应(ack)不受应用层影响,所以这个ack一般不会延迟。而发送fin报文则需要应用程序写close触发。所以这两个报文一般不合并。
Syn报文为啥三次握手
假如,如上图,把第二个syn ack报文拆开(红色的,现实和协议中规定这两个红色合为一个syn ack报文发送),拆成一个ack(响应服务器A的syn)和一个syn(服务器B的syn)
服务器B应用程序启动后,它的tcp协议栈就处于listen状态(等待对方建链),由于tcp链接又是全双工的,当服务器B收到syn报文后,syn和ack都不需要应用层参与,所以可以将将ack和syn合并一个报文。
半关闭
Tcp链接的一端(的应用程序)不再发送数据(通知自己的tcp发送了fin),而另一端继续发送数据,这种状态为半关闭。
以下是半关闭场景的tcp协议栈和应用程序的动作示意。
fin关闭分类
主动关闭(最先发起fin的一端为主动关闭,一般客户端)
被动关闭(后发起fin的一端为被动关闭,一般服务器)
同时关闭(同时发起fin,比较少见,但是tcp协议支持)
遗留问题:
1、 主动关闭发送fin并收到ack后,但是一直没有收到对方的fin,(比如对方应用挂了,或者这时候网络突然断了),怎么办?
2、 主动关闭,收到了对方的ack,也收到了对方的fin,并且也对对方的fin发送了ACK,但是这个最后的ACK在网络传输中丢了,怎么办?