您的位置:首页 > 理论基础 > 计算机网络

(转)TCP建立连接为什么需要三次握手

2019-02-22 13:53 330 查看

原起

众所周知tcp传输层协议在建立连接的时候需要三次才能建立起一个真正的可靠连接,可是为什么是三次呢,不可以是两次,四次等等呢?

三次握手

在《计算机网络》一书中其中有提到,三次握手的目的是“为了防止已经失效的连接请求报文段突然又传到服务端,因而产生错误”,这种情况是:一端(client)A发出去的第一个连接请求报文并没有丢失,而是因为某些未知的原因在某个网络节点上发生滞留,导致延迟到连接释放以后的某个时间才到达另一端(server)B。本来这是一个早已失效的报文段,但是B收到此失效的报文之后,会误认为是A再次发出的一个新的连接请求,于是B端就向A又发出确认报文,表示同意建立连接。如果不采用“三次握手”,那么只要B端发出确认报文就会认为新的连接已经建立了,但是A端并没有发出建立连接的请求,因此不会去向B端发送数据,B端没有收到数据就会一直等待,这样B端就会白白浪费掉很多资源。如果采用“三次握手”的话就不会出现这种情况,B端收到一个过时失效的报文段之后,向A端发出确认,此时A并没有要求建立连接,所以就不会向B端发送确认,这个时候B端也能够知道连接没有建立。

问题的本质是,信道是不可靠的,但是我们要建立可靠的连接发送可靠的数据,也就是数据传输是需要可靠的。在这个时候三次握手是一个理论上的最小值,并不是说是tcp协议要求的,而是为了满足在不可靠的信道上传输可靠的数据所要求的。

我们再来考虑,如果不是三次握手会出现什么情况呢:

假设有A和B两端要进行通信,
1, 第一次:首先A发送一个(SYN)到B,意思是A要和B建立连接进行通信;

如果是只有一次握手的话,这样肯定是不行的,A压根都不知道B是不是收到了这个请求。

2, 第二次:B收到A要建立连接的请求之后,发送一个确认(SYN+ACK)给A,意思是收到A的消息了,B这里也是通的,表示可以建立连接;

如果只有两次通信的话,这时候B不确定A是否收到了确认消息,有可能这个确认消息由于某些原因丢了。

3, 第三次:A如果收到了B的确认消息之后,再发出一个确认(ACK)消息,意思是告诉B,这边是通的,然后A和B就可以建立连接相互通信了;

这个时候经过了三次握手,A和B双方确认了两边都是通的,可以相互通信了,已经可以建立一个可靠的连接,并且可以相互发送数据。

4, 第四次:这个时候已经不需要B再发送一个确认消息了,两边已经通过前三次建立了一个可靠的连接,如果再发送第四次确认消息的话,就浪费资源了。

如果第二个报文段B发出的(SYN+ACK)分别发送的话,也是可以理解为四次,但是被优化了,一起发送了。

超时重传机制

(1) 如果第一个包,A发送给B请求建立连接的报文(SYN)如果丢掉了,A会周期性的超时重传,直到B发出确认(SYN+ACK);
(2) 如果第二个包,B发送给A的确认报文(SYN+ACK)如果丢掉了,B会周期性的超时重传,直到A发出确认(ACK);
(3) 如果第三个包,A发送给B的确认报文(ACK)如果丢掉了,

  • A在发送完确认报文之后,单方面会进入ESTABLISHED的状态,B还是SYN_RCVD状态
  • 如果此时双方都没有数据需要发送,B会周期性的超时发送(SYN+ACK),直到收到A的确认报文(ACK),此时B也进入ESTABLISHED状态,双方可以发送数据;
  • 如果A有数据发送,A发送的是(ACK+DATA),B会在收到这个数据包的时候自动切换到ESTABLISHED状态,并接受数据(DATA);
  • 如果这个时候B要发送数据,B是发送不了数据的,会周期性的超时重传(SYN+ACK)直到收到A的确认(ACK)B才能发送数据。

三次握手牵扯到的状态转换

  • ** LISTEN ** 表示socket已经处于listen状态了,可以建立连接;
  • ** SYN_SENT ** 表示socket在发出connect连接的时候,会首先发送SYN报文,然后等待另一端发送的确认报文(ACK),表示这端已经发送完SYN报文了;
  • ** SYN_RCVD ** 表示一端已经接收到SYN报文了;
  • ** ESTABLISHED ** 表示已经建立连接了,可以发送数据了。

转载地址:https://www.jianshu.com/p/e7f45779008a

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: