TCP建立连接为什么需要三次握手和结束连接为什么需要四次挥手

TCP概述

  • TCP是运输层的传输控制协议。
  • TCP提供了一种面向连接的(connection-oriented)、可靠的字节流服务
  • 面向连接是指:使用TCP的两个应用程序必须在它们可交换数据之前,通过相互联系建立一个TCP连接。
  • TCP提供了全双工通信。TCP允许通信双方在任何时候都能发送数据。TCP连接的两端
  • 都设置有发送缓存和接收缓存,用来临时存放通信双方的数据。

TCP报文段的首部 

TCP头部,标准长度为20字节,以32位为单位 

TCP建立连接为什么需要三次握手和结束连接为什么需要四次挥手_第1张图片

  • 源端口和目的端口
  1. 每个TCP头部包含了源端口和目的端口,这和IP头部中的源IP和目的IP一起,
  2. 唯一的标识了每个连接。
  3. 一个IP和端口的组合成为一个套接字(Socket)
  4. 每个TCP连接由一对套接字(客户端的IP和端口以及服务器的IP和端口)唯一的标识
  • 序列号(Sequence number)
  1. 占4个字节 [0,(2^32)-1] ,序列号增加到(2^32)-1后,下一个序号又回到0。
  2. 序列号标识了TCP发送端到接收端数据流的一个字节。
  3. 一个TCP连接传送的字节流中每一个字节都按顺序编号。
  4. 首部中的序列号指的是本报文所发送数据的第一个字节的序列号。
  5. 例如:一报文段的序列号为301,携带的数据有100字节,这就表明该报文段数据
  6. 的第一个字节为301,最后一个字节的序列号为401。
  • 确认号
  1. ACK中的确认号就是发送这个ACK的一端所期待的下一个序列号。
  2. 即最后被成功接收字节对应的序列号+1.
  3. B正确的收到A发过来的报文段,其序列号为501,而数据大小为200字节。这个
  4. 报文段的序列号为(501-700),这表明B收到了A发送的序列号到700为止的数据。
  5. 所以B期望下一个报文段的序列号为701.于是B在发送给A的确认报文段中
  6. 将确认号置为701.
  • 窗口
  1. 通知接收方,发送的报文需要多大的空间来接收

TCP连接的建立(三次握手) 

TCP建立连接为什么需要三次握手和结束连接为什么需要四次挥手_第2张图片

1、客户端发送一个SYN报文段,并指明自己想要连接服务器IP和端口号以及要发送数据的初始化序列号
2、服务器确认(ACK)客户端发送的SYN,同时自己也要发送SYN报文段和服务器要发送数据的初始化序列号。ACK的值为其包含的初始化序列号值加1
3、客户端确认服务器的SYN。将服务器的初始化序列号加1返回

 

为什么是三次握手?A为什么最后还要发送一次确认?

为了防止已经失效的连接请求报文段又突然传到服务端,因而产生错误。
A发送的一个连接请求在网络结点的时间滞留,以至于延误到连接释放的某个
时间才到达B。B收到这个请求的报文段后,误以为A又发出了一次新的请求连接,
于是向A发送确认报文段,同一建立连接。但是由于A并没有发出新的请求连接,
所以A不会理睬B的确认也不会向B发送数据。但B却认为连接已经建立,一直
等待A发来数据。B的资源就白白浪费了。

如果采用三次握手,B收到失效的报文段后向A发送确认,但是A并没有要求建立连接,就不会向B发送确认,这时候B也就知道请求没有建立。本质原因是信道是不可靠的。 

TCP的连接释放,四次挥手 

TCP建立连接为什么需要三次握手和结束连接为什么需要四次挥手_第3张图片

1,A发送一个FIN,代表数据发送完毕,其序列号为u,它等于前面已传送数据最后一个字节的序列号+1
2,B收到A的释放报文段后发出确认,确认号ACK=u+1,确认报文段的序列号为v。A到B这个方向上的连接就释放了。
3,B发送释放报文段FIN,B还需要重复上次发送的ACK,B放的报文段序列号为w,等待A的确认。
4,A在收到B的释放报文段后,需要确认。确认号为w+1

 

为什么是四次挥手?

为什么不是三次或者五次?

因为TCP的通信是全双工通信。 要实现可靠的连接关闭,A发送结束报文FIN,收到B的确认后。A知道自己没有 数据要发送,B知道A不再发送数据。但是B还可以发送数据,A还可以接收数据。 只有当B发送结束报文FIN,收到A的确认后,才算是真正的断开连接。

为什么客户端在TIME-WAIT(时间等待)状态必须等到2MSL(最长报文段寿命:Maximum Segment Lifetime,MSL)的时间?这有两个理由。

答:第一,为了保证A发送的最后一个ACK报文段能够到达B。这个ACK报文段有可能丢失,因而使处在LAST-ACK状态的B收不到对已发送的FIN+ACK报文段的确认。B会超时重传这个FIN+ACK报文段,而A就能在2MSL时间内收到这个重传的FIN+ACK报文段。接着A重传一次确认,重新启动2MSL计时器。最后A和B都正常进入到CLOSED状态。如果A在TIME-WAIT状态不等待一段时间,而是在发送完ACK报文段后立即释放连接,那么就无法收到B重传的FIN+ACK报文段,因而不会再发送一次 确认报文段。这样,B就无法按照正常步骤进入CLOSED状态。

  第二,防止上一节提到的“已失效的连接请求报文段”出现在本连接中。A在发送完最后一个ACK报文段后,再经过2MSL,就可以使本连接持续的时间内所产生的所有报文段都从网络中 消失。这样就可以使下一个新的连接中不会出现这种旧的连接请求报文段。

  B只有收到了A发出的确认,就进入CLOSED状态。同样,B在撤销相应的传输控制块TCB后就结束了这次的TCP连接。我们注意到,B结束TCP连接的时间比A早一些。

出现太多TIME_WAIT可能导致的后果:

在高并发短连接的TCP服务器上,当服务器处理完请求后立刻按照主动正常关闭连接。这个场景下,会出现大量socket处于TIMEWAIT状态。如果客户端的并发量持续很高,此时部分客户端就会显示连接不上。
我来解释下这个场景。主动正常关闭TCP连接,都会出现TIMEWAIT。为什么我们要关注这个高并发短连接呢?有两个方面需要注意:

 ① 高并发可以让服务器在短时间范围内同时占用大量端口,而端口有个0~65535的范围,并不是很多,刨除系统和其他服务要用的,剩下的就更少了。
 ②在这个场景中,短连接表示“业务处理+传输数据的时间 远远小于 TIMEWAIT超时的时间”的连接。这里有个相对长短的概念,比如,取一个web页面,1秒钟的http短连接处理完业务,在关闭连接之后,这个业务用过的端口会停留在TIMEWAIT状态几分钟,而这几分钟,其他HTTP请求来临的时候是无法占用此端口的。单用这个业务计算服务器的利用率会发现,服务器干正经事的时间和端口(资源)被挂着无法被使用的时间的比例是 1:几百,服务器资源严重浪费。(说个题外话,从这个意义出发来考虑服务器性能调优的话,长连接业务的服务就不需要考虑TIMEWAIT状态。同时,假如你对服务器业务场景非常熟悉,你会发现,在实际业务场景中,一般长连接对应的业务的并发量并不会很高)
     综合这两个方面,持续的到达一定量的高并发短连接,会使服务器因端口资源不足而拒绝为一部分客户服务。

time_wait状态如何避免

首先服务器可以设置SO_REUSEADDR套接字选项来通知内核,如果端口忙,但TCP连接位于TIME_WAIT状态时可以重用端口。在一个非常有用的场景就是,如果你的服务器程序停止后想立即重启,而新的套接字依旧希望使用同一端口,此时SO_REUSEADDR选项就可以避免TIME_WAIT状态。

你可能感兴趣的:(网络)