TCP三次握手与四次挥手
来自微信公众号——Java后端技术
一、TCP三次握手
1、客户端发送syn(Synchronize Sequence Numbers 同步序列编号)握手信号,
2、服务端回应ack(Acknowledgement)确认字符,并发送syn以确认客户端是否请求的是自己,
3、客户端接收到服务端发送的ack后,进入established状态,并就服务端发送的syn,回复ack确认字符,
4、服务端收到确认信息(字符),进去established状态。

有两个中间状态,syn_sent和syn_rcvd,这两个状态叫着「半打开」状态,就是向对方招手了,但是还没来得及看到对方的点头微笑。syn_sent是主动打开方的「半打开」状态,syn_rcvd是被动打开方的「半打开」状态。客户端是主动打开方,服务器是被动打开方。
-
syn_sent: syn package has been sent
-
syn_rcvd: syn package has been received
二、TCP数据传输
客户端向服务端发送data,服务端接收到后要向客户端回应ack。如果这个过程中data没有顺利传到服务端,或者客服端没有接收到ack,就需要重发data,称为tcp重传。在重传的情况下,服务端有可能用一个data接收到了两次,需要执行去重操作。「重传」和「去重」工作操作系统的网络内核模块都已经帮我们处理好了,用户层是不用关心的。
客户端可以向服务端发送数据,同样服务端也能向客户端发送数据,因为tcp链接是「双工的」,双方都可以主动发送数据传输,不过无论是哪方发送,都需要收到对方的确认才能认为对方收到了自己发送的数据。
「批量ack」——客户端连续性发送多条data,此时服务端不用一句一句回复,而是在连续接收完后,向客户端回复ack。
「TCP窗口大小」——客户端一次性不能发送太多data,服务端一次性无效处理太多消息,两端之间需要有协商好的合适的发送和接受速率。
网络环境的数据交互存在数据包乱序的现象。同一个来源发出来的不同数据包在「网际路由」上可能会走过不同的路径,最终达到同一个地方时,顺序就不一样了。操作系统的网络内核模块会负责对数据包进行排序,到用户层时顺序就已经完全一致了。
三、TCP四次挥手
TCP断开链接的过程和建立链接的过程比较类似,只不过中间的两部并不总是会合成一步走,所以它分成了4个动作。

之所以中间的两个动作没有合并,是因为tcp存在「半关闭」状态,也就是单向关闭。客户端虽然关闭,但只是不再主动发送data,但是还是可以接收收据,服务端继续发送数据。等待服务端不再发送data,向客户端发送fin结束标志,客户端回应ack,才彻底结束了。
上面有一个非常特殊的状态time_wait,它是主动关闭的一方在回复完对方的挥手后进入的一个长期状态,这个状态标准的持续时间是4分钟,4分钟后才会进入到closed状态,释放套接字资源(不过在具体实现上这个时间是可以调整的)。
就好像提出主动分手那方告知对方(发送fin),对方收到分手的消息,表示知道了这个消息(回应ack),主动方就不说话了,对方或是数落主动方的不是,或是寻求一个解释,或是歇斯底里(可以继续像主动方发送data),但是主动方不会再主动说话(不再主动发送data),直到对方累了,同意分手(发送fin),主动方接收到fin,进入time_wait状态,回复对方表示知道了(回应ack)。在4分钟的time_wait状态里,要确保对方接收到回应ack,如果对方没接收到ack,则对方要重新发送同意分手的消息(重传fin)。
time_wait的作用是重传最后一个ack报文,确保对方可以收到。因为如果对方没有收到ack的话,会重传fin报文,处于time_wait状态的套接字会立即向对方重发ack报文。
同时在这段时间内,该链接在对话期间于网际路由上产生的残留报文(因为路径过于崎岖,数据报文data走的时间太长,重传的报文都收到了,原始报文还在路上)传过来时,都会被立即丢弃掉。4分钟的时间足以使得这些残留报文彻底消逝。不然当新的端口被重复利用时,这些残留报文可能会干扰新的链接。
4分钟就是2个MSL,每个MSL是2分钟。MSL就是maximium segment lifetime——最长报文寿命。这个时间是由官方RFC协议规定的。至于为什么是2个MSL而不是1个MSL,不知
四次挥手也并不总是四次挥手,中间的两个动作有时候是可以合并一起进行的(主动方请求分手,对方立即同意),这个时候就成了三次挥手,主动关闭方就会从fin_wait_1状态直接进入到time_wait状态,跳过了fin_wait_2状态。
浙公网安备 33010602011771号