1. TCP三次握手
TCP三次握手.png为什么需要三次握手呢?为了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误。
比如:client发出的第一个连接请求报文段并没有丢失,而是在某个网络结点长时间的滞留了,以致延误到连接释放以后的某个时间才到达server。本来这是一个早已失效的报文段,但是server收到此失效的连接请求报文段后,就误认为是client再次发出的一个新的连接请求,于是就向client发出确认报文段,同意建立连接。假设不采用“三次握手”,那么只要server发出确认,新的连接就建立了,由于client并没有发出建立连接的请求,因此不会理睬server的确认,也不会向server发送数据,但server却以为新的运输连接已经建立,并一直等待client发来数据。所以没有采用“三次握手”,这种情况下server的很多资源就白白浪费掉了。
理解如下场景:
说白了整个建立连接三次握手过程就像这样的场景:
- (1). 一男一女在一个咖啡厅相亲,男的(客户端)先问:
你觉得我怎么样?
(第一次握手) - (2). 女的回答:
我觉得你很帅
然后 问了男的一句:你觉得我漂亮么?
,想确认一下男方的意见。(第二次握手) - (3). 男的听到女的回答心里早就乐开了花,巴不得马上牵着女方的小手,回答:
我觉得你就是我的女神,我们在一起吧
,到此牵手成功。(第三次握手)建立连接。 - (4).
如果上面3步少了任何一步都不能牵手
,要两个人都同意,都确认后才能建立连接。
2. TCP四次挥手
TCP四次挥手.png为什么需要四次挥手呢?
TCP是全双工模式,当client发出FIN报文段时,只是表示client已经没有数据要发送了,client告诉server,它的数据已经全部发送完毕了;但是,这个时候client还是可以接受来server的数据;当server返回ACK报文段时,表示它已经知道client没有数据发送了,但是server还是可以发送数据到client的;当server也发送了FIN报文段时,这个时候就表示server也没有数据要发送了,就会告诉client,我也没有数据要发送了,如果收到client确认报文段,之后彼此就会愉快的中断这次TCP连接。
理解如下场景:
- (1). 相亲的男女在一起相处了一阵子,开始闹矛盾了,女的性子比较急一点,先提出分手(女方相当于客户端)女的说:
我受够你了,你就是个矮矬穷,我要的白马王子应该是高富帅才对
。 (第一次挥手:FIN M)第一次挥手后进入了 Finish_Wait_1状态 - (2). 男的觉得女的还挺好的,很漂亮,就是性格有点倔强,不想分手,男的还想给女的说很多话去挽留。此时男的说:
我已经知道你要和我分手的信息了
(ack+1),然后又向女的说了很多挽留的话,此时只有男的向女的说话(服务器--》客户端)半双工。(第二次挥手: ack M+1) (服务器收到第一次挥手的信息后,就进入Close_Wait状态,但是还可以像客户端继续发送没有发送完的信息,然后发送一个确认包:ack = M+1) - (3). 男的思考了很近说了很多话挽留都无效,然后男绝望的说了一句:
我们真的要分手吗
再次确认一下 (FIN N)然后等待女方的回答,不再向女方说话了。(第三次挥手)(此时服务器进入了LAST_ACK最后确认状态) - (4). 女的听到男的说的话之后, 有些犹豫了,如果她想反悔了,就可以跟男的说:
我不想分手了
这样分手就失败了,如果她还是坚持她自己原生相反,坚决要分手,她就会说:我想了很久,我们真的不合适,我们还是分手吧
(第四次挥手:ACK=1, ack = K +1 )。(此时客户端进入Time_Wait状态,等待一个2MSL时间就会关闭连接) - (5). 男方收到女方的信息,如果男方决定要分手,就会直接Close()关闭通话状态,不必再发信息给女方了,如果男方决定不分手了,就会再跟女的说:
我们不分手了
,到此分手就已失败结束了。(这里服务器会比客户端 先关闭连接状态,客户端需要等待一个最长2MSL
的时间)
1.为什么最后客户端还要等待
2*MSL
的时间呢?
MSL(Maximum Segment Lifetime),TCP允许不同的实现可以设置不同的MSL值。
第一,保证客户端发送的最后一个ACK报文能够到达服务器,因为这个ACK报文可能丢失,站在服务器的角度看来,我已经发送了FIN+ACK报文请求断开了,客户端还没有给我回应,应该是我发送的请求断开报文它没有收到,于是服务器又会重新发送一次,而客户端就能在这个2MSL时间段内收到这个重传的报文,接着给出回应报文,并且会重启2MSL计时器。
第二,防止类似与“三次握手”中提到了的“已经失效的连接请求报文段”出现在本连接中。客户端发送完最后一个确认报文后,在这个2MSL时间中,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失。这样新的连接中不会出现旧连接的请求报文。
为什么建立连接是三次握手,关闭连接确是四次挥手呢?
1.建立连接的时候, 服务器在LISTEN状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。
2.关闭连接时,客户端向服务端发送 FIN 时,仅仅表示客户端不再发送数据了但是还能接收数据,而自己也未必全部数据都发送给对方了,服务器收到客户端的 FIN 报文时,先回一个 ACK 应答报文,而服务端可能还有数据需要处理和发送,等服务端不再发送数据时,才发送 FIN 报文给客户端来表示同意现在关闭连接。从上面过程可知,服务端通常需要等待完成数据的发送和处理,所以服务端的 ACK 和 FIN 一般都会分开发送,从而比三次握手导致多了一次。
网友评论