由于网上关于TCP三次握手四次挥手的内容已经很丰富,所以我们今天趣味讲解一下TCP三次握手和四次挥手。
三次握手:
首先先上图:
由于我给客户端和服务端都上了色,所以暂且就叫他们小蓝(Client)和小绿(Server)就好了。
由于一次意外,两人都双目失明,看不见了。他们只能通过声音辨认对方。
这其中还有两个中间态:syn_sent和syn_rcvd,这两个状态叫【半打开】状态,也就是两人呼唤对方。Syn_sent是客户端的半打开状态,sun_rcvd是服务端的半打开状态。
Syn_sent : syn package has been sent
Syn_rcvd : syn package has been received
官方语言:
四次挥手:
两人离别的时候,
官方语言:
状态time_wait是一个非常特殊的状态,它是主动关闭的一方在回复完对方后进入的一个长期状态,这个状态标准的持续时间是4分钟,4分钟后才会进入到closed状态,释放套接字资源。不过在具体实现上这个时间是可以调整的。
这个后果就是持续4分钟的time_wait状态,不能释放套接字资源(端口),就好比守寡期,这段时间内套接字资源(端口)不得回收利用。
它的作用是重传最后一个ack报文,确保对方可以收到。因为如果对方没有收到ack的话,会重传fin报文,处于time_wait状态的套接字会立即向对方重发ack报文。
同时在这段时间内,该链接在对话期间于网际路由上产生的残留报文(因为路径过于崎岖,数据报文走的时间太长,重传的报文都收到了,原始报文还在路上)传过来时,都会被立即丢弃掉。4分钟的时间足以使得这些残留报文彻底消逝。不然当新的端口被重复利用时,这些残留报文可能会干扰新的链接。
4分钟就是2个MSL,每个MSL是2分钟。MSL就是maximium segment lifetime——最长报文寿命。这个时间是由官方RFC协议规定的。至于为什么是2个MSL而不是1个MSL呢?
第一,保证客户端发送的最后一个ACK报文能够到达服务器,因为这个ACK报文可能丢失,站在服务器的角度看来,我已经发送了FIN+ACK报文请求断开了,客户端还没有给我回应,应该是我发送的请求断开报文它没有收到,于是服务器又会重新发送一次,而客户端就能在这个2MSL时间段内收到这个重传的报文,接着给出回应报文,并且会重启2MSL计时器。
第二,防止”已经失效的连接请求报文段”出现在本连接中。客户端发送完最后一个确认报文后,在这个2MSL时间中,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失。这样新的连接中不会出现旧连接的请求报文。
最后一个问题,为什么建立连接是三次握手,关闭连接确是四次挥手呢?
建立连接的时候, 服务器在LISTEN状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。
而关闭连接时,服务器收到对方的FIN报文时,仅仅表示对方不再发送数据了但是还能接收数据,而自己也未必全部数据都发送给对方了,所以己方可以立即关闭,也可以发送一些数据给对方后,再发送FIN报文给对方来表示同意现在关闭连接,因此,己方ACK和FIN一般都会分开发送,从而导致多了一次。
四次挥手也并不总是四次挥手,中间的两个动作有时候是可以合并一起进行的,这个时候就成了三次挥手,主动关闭方就会从fin_wait_1状态直接进入到time_wait状态,跳过了fin_wait_2状态。
扩展:TCP数据传输
数据传输过程即是小蓝和小绿对话的过程。
只不过两人隔着河,且都看不见,所以当一方说话后(data)需要对方听到了回应一声(ACK)。
如果小蓝喊了一句,半天没听到小绿回复,小蓝就认为自己的话被大风吹走了,小绿没听见,所以需要重新喊话,这就是【tcp重传】。
也有可能是小绿听到了小蓝的话,但是小绿向小蓝的回复被大风吹走了,以至于小蓝没听见小绿的回复。小蓝并不能判断究竟是自己的话被大风吹走了还是小绿的回复被大风吹走了,小蓝也不用管,重传一下就是。
既然会重传,小绿就有可能同一句话听见了两次,这就是【去重】。【重传】和【去重】工作操作系统的网络内核模块都已经帮我们处理好了。
小蓝可以向小绿喊话,同样小绿也可以向小蓝喊话,因为tcp链接是「双工的」,双方都可以主动发起数据传输。不过无论是哪方喊话,都需要收到对方的确认才能认为对方收到了自己的喊话。
小蓝可能是个八卦,一说连说了八句话,这时候小绿可以不用一句一句回复,而是连续听了这八句话之后,一起向对方回复说前面你说的八句话我都听见了,这就是批量ack。但是小蓝也不能一次性说了太多话,小绿的脑子短时间可能无法消化太多,两人之间需要有协商好的合适的发送和接受速率,这个就是【TCP窗口大小】。
网络环境的数据交互同人类之间的对话还要复杂一些,它存在数据包乱序的现象。同一个来源发出来的不同数据包在「网际路由」上可能会走过不同的路径,最终达到同一个地方时,顺序就不一样了。操作系统的网络内核模块会负责对数据包进行排序,到用户层时顺序就已经完全一致了。
好了,今天就介绍到这里了,说的比较简单,深的等以后写,每天进步一点点,希望世界充满正能量!