一文看懂TCP三次握手和四次挥手

什么是TCP三次握手:

TCP通过三次握手建立连接。

1.服务端处于监听端口,listen状态

2.第一次握手:SYN报文

客户端随机初始化序列号client_isn,置于TCP首部的序列号字段中,同时把SYN标志设置为1,客户端处于SYN_SENT状态

3.第二次握手:SYN+ACK报文

服务端收到SYN报文后,随机初始化序列号serv_isn,然后将客户端序列号+1作为确认应答号。SYN和ACK标志位设置为1.发给客户端后处于SYN_RCVD

4.第三次握手:ACK报文

客户端收到服务端报文后,还要向服务端发送一个应答报文,确认应答号为serv_isn+1,ACK设置为1.这次可以携带数据到服务端,客户端处于ESTABLISHED状态。服务端收到后也进入ESTABLISHED状态。

为什么是三次握手?

1.阻止重复历史连接的初始化。

如果客户端发送时因为宕机(需要重启),发送了一个SYN报文,之后又发送一个新的SYN报文。

如果是旧报文先到,返回的ack会让客户端发送RST报文,服务端释放连接,新的SYN到了之后就会重新建立连接。如果发送RST之前,服务端收到了新SYN报文,那么服务端会返回旧连接的ACK,客户端依然会发送RST报文。

如果是新报文先到并建立了连接,旧报文再到就会被服务端根据序列号认定为旧连接不管。

如果是两次握手,收到SYN后直接进入ESTABLISHED状态,没有中间状态来阻止历史连接,造成资源浪费。

2.同步初始序列号。

序列号作用:

1.接收方可以去除重复的数据;
2.接收方可以根据数据包的序列号按序接收,
3.可以标识发送出去的数据包中, 哪些是已经被对方收到的(通过 ACK 报文中的序列号知道)

四次握手其实也能够可靠的同步双方的初始化序号,但由于第二步和第三步可以优化成一步,所以就成了三次握手。
而两次握手只保证了一方的初始序列号能被对方成功接收,没办法保证双方的初始序列号都能被确认接收。

3.避免资源浪费。

如果是两次握手,每次收到SYN,服务端都要建立连接,因为不知道客户端是不是收到了ACK。那么重复建立连接就会浪费资源。

IP报文会分片,为什么TCP报文有MSS限制长度?

因为如果TCP报文不限制长度,到传输层,IP报文超过了MTU(以太网报文长度),那么IP来分片,可能把TCP头部和数据拆分了,到目标主机的传输层组装。

那么如果中间一个IP分片丢失,全部都得重传,因为IP协议不具有超市重传和确认应答等特性。这些依靠TCP协议实现,所以应该保证TCP报文完整性,所以应该限制TCP报文长度,避免他被传输层分片。

所以,为了达到最佳的传输效能 TCP 协议在建立连接的时候通常要协商双方的 MSS 值

什么是TCP四次挥手?

TCP断开连接的方式:

我们可以把四次挥手分成两组来看,就是分别代表己方不在发送数据。

这里要注意先断开的才会进入time_wait状态。

客户端打算关闭连接,此时会发送一个TCP 首部 FIN 标志位被置为1的报文,也即 FIN 报文,
之后客户端进入 FIN_WAIT_1 状态。
服务端收到该报文后,就向客户端发送 AcK应答报文,接着服务端进入CLOSE_WAIT 状态。
客户端收到服务端的 ACK应答报文后,之后进入FIN_WAIT_2 状态。
等待服务端处理完数据后,也向客户端发送 FIN报文,之后服务端进入 LAST_ACK状态。
客户端收到服务端的 FIN报文后,回一个ACK 应答报文,之后进入TIME_WAIT 状态
服务端收到了 ACK应答报文后,就进入了CLOSE 状态,至此服务端已经完成连接的关闭,
客户端在经过2MSL时间后,自动进入 CLOSE状态,至此客户端也完成连接的关闭。

如果第一次挥手丢失?

发出第一个FIN报文后,进入FIN_WAIT_1状态,触发客户端FIN报文的超时重传,tcp_orphan_retries设置最大重传次数。最后一次再等待上次时间的两倍后就自动断开连接。

如果第二次挥手丢失?

服务端发送ACK后,进入CLOSE_WAIT状态。由于ACK报文不会重传,所以客户端(主动断开方)会不断发送FIN报文。类似于第一次挥手丢失。

如果第三次挥手丢失?

当服务端进程处于CLOSE_WAIT状态,进程调用close函数,发送FIN报文,进入LAST_ACK状态,FIN丢失,收不到ACK报文,进行超时重传,重发次数仍然由 tcp_orphan_retries 参数控制

如果第四次挥手丢失?

客户端收到FIN后,发送ACK,此时客户端进入TIME_WAIT状态,持续2MSL才进入close状态,但是丢失ACK,接受到重新发送的FIN,就会重置计时器。最后超时自动进入close。

服务端没有收到ACK,就还在LAST_ACK状态。多次重传后,自动进入close。

为什么有TIME_WAIT状态?

1.在这个时间内,中间可能发生网络延迟的报文都会被丢失,不会影响到后面的连接。

在TCP报文里有序列号的概念,在三次握手连接中,序列号称为初始化序列号,这个序列号每4us加1,所以如果前后连接间隔过短,有可能是同样的初始化序列号,

那么在前面的网络延迟的报文如果被下一次连接的客户端或者服务端接收到了,刚好在序列号的区间内,这样就导致了数据错乱。

而TIME_WAIT状态持续2MSL就能够保证两边的报文都会在这个时间内丢弃。

2.保证被动关闭连接的一方能够被正确关闭。

TIME_WAIT是主动发起断开连接的一方会处于的状态,也是为了保证被动方发送FIN后,自己的ACK能够传给被动方。避免被动方超时重传时,没有重新发送ACK。

客户端在收到服务端重传的 FIN 报文时,TIME_WAIT 状态的等待时间,会重置回 2MSL。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值