tcp为什么三次握手及四次挥手

三次握手

为什么在第3步中客户端还要再进行一次确认呢?这主要是为了防止已经失效的连接请求报文段突然又传回到服务端而产生错误的场景:
所谓"已失效的连接请求报文段"是这样产生的。正常来说,客户端发出连接请求,但因为连接请求报文丢失而未收到确认。于是客户端再次发出一次连接请求,后来收到了确认,建立了连接。数据传输完毕后,释放了连接,客户端一共发送了两个连接请求报文段,其中第一个丢失,第二个到达了服务端,没有"已失效的连接请求报文段"。

现在假定一种异常情况,即客户端发出的第一个连接请求报文段并没有丢失,只是在某些网络节点长时间滞留了,以至于延误到连接释放以后的某个时间点才到达服务端。本来这个连接请求已经失效了,但是服务端收到此失效的连接请求报文段后,就误认为这是客户端又发出了一次新的连接请求。于是服务端又向客户端发出请求报文段,同意建立连接。假定不采用三次握手,那么只要服务端发出确认,连接就建立了。由于现在客户端并没有发出连接建立的请求,因此不会理会服务端的确认,也不会向服务端发送数据,但是服务端却以为新的传输连接已经建立了,并一直等待客户端发来数据这样服务端的许多资源就这样白白浪费了。采用三次握手的办法可以防止上述现象的发生。比如在上述的场景下,客户端不向服务端的发出确认请求,服务端由于收不到确认,就知道客户端并没有要求建立连接。

四次挥手

这里的一个问题是,为什么TCP连接的建立只需要三次握手而TCP连接的释放需要四次握手呢:

因为服务端在LISTEN状态下,收到建立请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。而连接关闭时,当收到对方的FIN报文时,仅仅表示对方没有需要发送的数据了,但是还能接收数据,己方未必数据已经全部发送给对方了,所以己方可以立即关闭也可以将应该发送的数据全部发送完毕后再发送FIN报文给客户端来表示同意现在关闭连接

从这个角度而言,服务端的ACK和FIN一般都会分开发送。

半连接队列和全连接队列。
在三次握手中,客户端会向服务端发送两次连接请求,第一次服务端接受到连接请求时,会将该请求存入半连接队列,第二次服务端收到客户端的请求时,会将该请求从半连接队列中取出,然后存入全连接队列。若全连接队列已满,
在这里插入图片描述
1.服务端绑定某个端口并监听
2.客户端发送SYN给服务端发起第一次握手,此时服务端将此请求信息放在半连接队列中并回复SYN + ACK给客户端
3.客户端收到SYN+ACK,发起应答,回复一个ACK给服务端,假设此时全连接队列未满,那么从半连接队列中拿出此请求信息放入全连接队列中。如果全连接队列满了,那么客户端继续向服务端发送ACK,服务端的处理方式和系统参数tcp_abort_on_overflow有关,Linux环境下可以通过执行"cat /proc/sys/net/ipv4/tcp_abort_on_overflow"来查看此参数:
0表示字节丢弃该ACK
1表示发送一个RST给客户端,直接废掉这个握手过程与连接
4.服务端accept处理此请求,从全连接队列中将此请求信息拿出

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值