了解三次握手与四次挥手

了解三次握手与四次挥手

Posted by WangZiTao on Saturday, April 20, 2019

三次握手

TCP协议中,主动发起请求的一端称为『客户端』,被动连接的一端称为『服务端』。不管是客户端还是服务端,TCP连接建立完后都能发送和接收数据。

起初服务器和客户端都为CLOSED状态。在通信开始前双方都得创建各自的传输控制块(TCB)。 服务器创建完TCB后遍进入LISTEN状态,此时准备接收客户端发来的连接请求。

SYN 是发起一个连接
ACK 是回复
RST 是重新连接
FIN 是结束连接等

ACK=1: TCP连接请求报文段以外,TCP通信过程中所有数据报的ACK都为1,表示应答。

第一次握手

客户端向服务端发送连接请求报文段。该报文段的头部中SYN=1,ACK=0,seq=x。请求发送后,客户端便进入SYN-SENT状态。

PS1SYN=1ACK=0表示该报文段为连接请求报文。
PS2x为本次TCP通信的字节流的初始序号。
TCP规定:SYN=1的报文段不能有数据部分,但要消耗掉一个序号。

第二次握手

服务端收到连接请求报文段后,如果同意连接,则会发送一个应答:SYN=1,ACK=1,seq=y,ack=x+1。 该应答发送完成后便进入SYN-RCVD状态。

PS1SYN=1ACK=1表示该报文段为连接同意的应答报文。
PS2seq=y表示服务端作为发送者时,发送字节流的初始序号。
PS3ack=x+1表示服务端希望下一个数据报发送序号从x+1开始的字节。

第三次握手

当客户端收到连接同意的应答后,还要向服务端发送一个确认报文段,表示:服务端发来的连接同意应答已经成功收到。 该报文段的头部为:ACK=1,seq=x+1,ack=y+1。 客户端发完这个报文段后便进入ESTABLISHED状态,服务端收到这个应答后也进入ESTABLISHED状态,此时连接的建立完成!

各个状态名称与含义

CLOSED: 这个没什么好说的了,表示初始状态。 LISTEN: 这个也是非常容易理解的一个状态,表示服务器端的某个SOCKET处于监听状态,可以接受连接了。 SYN_RECV: 这个状态表示接受到了SYN报文,在正常情况下,这个状态是服务器端的SOCKET在建立TCP连接时的三次握手会话过程中的一个中间状态,很短暂,基本 上用 netstat你是很难看到这种状态的,除非你特意写了一个客户端测试程序,故意将三次TCP握手过程中最后一个ACK报文不予发送。因此这种状态 时,当收到客户端的ACK报文后,它会进入到ESTABLISHED状态。 SYN_SENT: 这个状态与SYN_RECV遥想呼应,当客户端SOCKET执行CONNECT连接时,它首先发送SYN报文,因此也随即它会进入到了SYN_SENT状 态,并等待服务端的发送三次握手中的第2个报文。SYN_SENT状态表示客户端已发送SYN报文。 ESTABLISHED:这个容易理解了,表示连接已经建立了。

为什么连接建立需要三次握手,而不是两次握手

防止失效的连接请求报文段被服务端接收,从而产生错误。

PS:失效的连接请求:若客户端向服务端发送的连接请求丢失,客户端等待应答超时后就会再次发送连接请求,此时,上一个连接请求就是『失效的』。

若建立连接只需两次握手,客户端并没有太大的变化,仍然需要获得服务端的应答后才进入ESTABLISHED状态,而服务端在收到连接请求后就进入ESTABLISHED状态。此时如果网络拥塞,客户端发送的连接请求迟迟到不了服务端,客户端便超时重发请求,如果服务端正确接收并确认应答,双方便开始通信,通信结束后释放连接。此时,如果那个失效的连接请求抵达了服务端,由于只有两次握手,服务端收到请求就会进入ESTABLISHED状态,等待发送数据或主动发送数据。但此时的客户端早已进入CLOSED状态,服务端将会一直等待下去,这样浪费服务端连接资源。

四次挥手

TCP连接的释放一共需要四步,因此称为『四次挥手』。 我们知道,TCP连接是双向的,因此在四次挥手中,前两次挥手用于断开一个方向的连接,后两次挥手用于断开另一方向的连接。

第一次挥手

若A认为数据发送完成,则它需要向B发送连接释放请求。该请求只有报文头,头中携带的主要参数为:

FIN=1seq=u

此时,A将进入FIN-WAIT-1状态。
PS1FIN=1表示该报文段是一个连接释放请求。
PS2seq=uu-1AB发送的最后一个字节的序号。

第二次挥手

B收到连接释放请求后,会通知相应的应用程序,告诉它A向B这个方向的连接已经释放。此时B进入CLOSE-WAIT状态,并向A发送连接释放的应答,其报文头包含:

ACK=1seq=vack=u+1

PS1ACK=1:除TCP连接请求报文段以外,TCP通信过程中所有数据报的ACK都为1,表示应答。
PS2seq=vv-1BA发送的最后一个字节的序号。
PS3ack=u+1表示希望收到从第u+1个字节开始的报文段,并且已经成功接收了前u个字节。

A收到该应答,进入FIN-WAIT-2状态,等待B发送连接释放请求。

第二次挥手完成后,A到B方向的连接已经释放,B不会再接收数据,A也不会再向B发送数据报文(第四次应答是确认报文(ACK=1),无数据)。但B到A方向的连接仍然存在,B可以继续向A发送数据报文

第三次挥手

当B向A发完所有数据后,向A发送连接释放请求,请求头:FIN=1,ACK=1,seq=w,ack=u+1。B便进入LAST-ACK状态。

第四次挥手

A收到释放请求后,向B发送确认应答,此时A进入TIME-WAIT状态。 该状态会持续2MSL时间,若该时间段内没有B的重发请求的话,就进入CLOSED状态,撤销TCB。当B收到确认应答后,也便进入CLOSED状态,撤销TCB。

为什么A要先进入TIME-WAIT状态,等待2MSL时间后才进入CLOSED状态?

为了保证B能收到A的确认应答。 若A发完确认应答后直接进入CLOSED状态,那么如果该应答丢失,B等待超时后就会重新发送连接释放请求,但此时A已经关闭了,不会作出任何响应,因此B永远无法正常关闭。

下面附加一个知乎上答案的问答

:问一下如果第四次挥手没有成功……. 主动方已经关闭了通道,但是因为被动方没有成功收到连接中断的确认,会一直在那边等?

:第四次挥手主动方会等待2MSL 如果第四次挥手没成功 那么被动方会重发FIN=1的请求

追问:那么被动方是怎么知道第四次挥手有没有成功的? 如果第四次挥手失败,对于被动方来说它只是一直没有等到主动方的ACK消息…. 有可能被动方一直在那边等,然后等了2MSL以后还是没有收到主动方的ACK, 然后其实这个时候主动方已经关闭了,但是被动方还开着?

追答:最后一次挥手,主动方向被动方发送确认报文(ACK=1) ,若挥手失败,确认报文则未发送到被动方 。 超时后被动方则会重传FIN=1的报文给主动方,重新进行第四次挥手 。 而主动方所需要等待的时间两个最大报文生存时间, 恰恰是为了被动方重发FIN=1的消息时主动方有充足的时间可以收到。 所以就可以避免了仅有一方关闭的情况发生。

追问:超时后被动方则会重传FIN=1的报文给主动方 这个超时是指多久呢?

追答:一个最大报文生存周期。

追答:最大报文生存周期MSL(Maximum Segment Lifetime),被动方等待MSL,主动方等待2MSL。

参考图

放两张参考文章的图:

参考文章

再深谈TCP/IP三步握手&四步挥手原理及衍生问题—长文解剖IP TCP为什么是四次挥手,而不是三次?


comments powered by Disqus