一篇文章彻底搞懂 TCP 三次握手、四次挥手

首先看TCP的报文格式:
在这里插入图片描述

三次握手

  1. 客户端要给服务端发送一个建立连接的请求(请求里有一个标志位SYN=1,并且会初始化一个32位的随机序列号seqA
  2. 这时服务器就知道客户端要建立一个连接,然后就会回一个东西(有标志位SYN=1,随机生成一个32位的序列号sqeBACK=1,消息确认序号ack包,ack=seq+1(这个操作是为了告诉服务端,下次发的报文需要从ack开始))
  3. 客户端在收到服务端的消息后,需要确认下ack是否等于seqA+1,是的话就立马给服务端发一个确认报文(ACK=1,ack=ackB+1)

在这里插入图片描述
如果只建立两次链接可以吗?

当然不行。因为客户端给服务端发送得报文可能会因为网络延迟,导致报文过期,但网络正常后服务端依旧会收到这个报文。这时它就会给客户端响应连接,由于现在客户端并没有发出建立连接的请求,因此不会理睬服务端的确认,也不会向服务端发送数据。但服务端却以为新的运输连接已经建立,并一直等待客户端发来数据。这样,服务端的很多资源就白白浪费掉了。

其次,两次握手无法保证Client正确接收第二次握手的报文(Server无法确认Client是否收到),也无法保证Client和Server之间成功互换初始序列号。

第三次握手中,如果客户端的ACK未送达服务器,会怎样?

Server端

由于Server没有收到ACK确认,因此会重发之前的SYN+ACK(默认重发五次,之后自动关闭连接进入CLOSED状态),Client收到后会重新传ACK给Server。

Client端,两种情况:

  1. 在Server进行超时重发的过程中,如果Client向服务器发送数据,数据头部的ACK是为1的,所以服务器收到数据之后会读取 ACK number,进入 establish 状态。
  2. 在Server进入CLOSED状态之后,如果Client向服务器发送数据,服务器会以RST包应答。

如果已经建立了连接,但客户端出现了故障怎么办?

服务器每收到一次客户端的请求后都会创建一个计时器,倒计时通常是设置为2小时。若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75秒钟发送一次。若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接。


四次挥手

即客户端想要断开连接

  1. 客户端给服务端发送一个报文(FIN=1,seqA序列号)
  2. 服务端收到后就会发送一个确认报文(ACK=1,ack=seqA+1),此时客户端已经没有要发送的数据了,但仍可以接受服务器发来的数据(即处于半关传输阶段)。
  3. 服务端会接着再发一个消息(FIN=1,seqB序列号)
  4. 客户端要收到了服务端的消息后,进入TIME_WAIT状态,并发一个消息确认包(ACK=1,ack=seqB+1)。服务器收到后,确认ack包后,变为CLOSED状态,不再向客户端发送数据。客户端等待2*MSL(报文段最长寿命)时间后,也进入CLOSED状态。完成四次挥手。
    在这里插入图片描述

它为什么要这么挥手?第二步跟第三步为什么不能合并在一起?

因为服务器收到客户端断开连接的请求时,可能还有一些数据没有发完,这时先回复ACK,表示接收到了断开连接的请求。等到数据发完之后再发FIN,断开服务器到客户端的数据传送。

如果第二次挥手时服务器的ACK没有送达客户端,会怎样?

客户端没有收到ACK确认,会重新发送FIN请求。

第四次挥手,客户端为什么要等待2MSL?(客户端TIME_WAIT状态的意义?)

第四次挥手时,客户端发送给服务器的ACK有可能丢失,TIME_WAIT状态就是用来重发可能丢失的ACK报文。如果Server没有收到ACK,就会重发FIN,如果Client在2*MSL的时间内收到了FIN,就会重新发送ACK并再次等待2MSL,防止Server没有收到ACK而不断重发FIN。

并且如果client直接closed,然后又向server发起了一个新连接,我们不能保证这个新连接和刚关闭的连接的端口号是不同的。假设新连接和已经关闭的老端口号是一样的,如果前一次滞留的某些数据仍然在网络中,这些延迟数据会在新连接建立后到达Server,所以socket就认为那个延迟的数据是属于新连接的,数据包就会发生混淆。所以client要在TIME_WAIT状态等待2倍的MSL,这样保证本次连接的所有数据都从网络中消失。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值