问:请你讲一下三次握手的过程?
image.png
image.png
答:
在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立连接。

第一次握手:客户端A向服务器B发出连接请求报文段,首部中同步位SYN = 1,选择一个序号seq = x,但是并没有携带数据。TCP客户端进程进入SYN-SENT(同步已发送)状态

第二次握手:服务器B收到请求报文段,如同意连接,向A发送确认。
确认报文段中,同步位SYN = 1, 确认ACK = 1,确认号 x + 1(表明希望收到对方报文第一个字节序号为x + 1),同时选择一个初始序号seq = y。TCP服务器进程进入SYN-RCVD(同步收到)状态

第三次握手:TCP客户进程收到B的确认后,向服务器进程B确认。
确认报文中,ACK为置为1,确认号为y + 1,自己的序列为 x + 1
TCP的标准规定,ACK报文段可以携带数据。但如果不携带数据则不消耗序号,在这种情况下,下一个数据报文段的序号仍是seq = x + 1。这时,TCP连接已经建立,A进入ESTABLISHED(已建立连接)状态

当B收到A的确认后,也进入ESTABLISHED状态。


TCP连接是全双工的,因此需要分别确认A的初始序列号和确认B的初始序列号。

问:握手时产生的序列号有什么用?
答:
TCP是面向字节的,且字节流传输需要按序到达。在建立连接时,通信双方都要互相通知对方自己的序列号,这个序列号作为以后数据通信的起始序列号,保证接收到的数据有序。
此外,TCP还会使用这个序号来拼接数据。

问:为什么必须三次握手,两次可以吗?
答:
为了防止已失效的连接请求报文段突然又传送到了服务端进程,因而产生错误。

所谓“已失效的连接请求报文段”是这样产生的。考虑一种正常情况。A发出连接请求,但因连接请求报文丢失而未收到确认。于是A再重传一次连接请求。后来收到了确认,建立了连接。数据传输完毕后,就释放了连接。A共发送了两个连接请求报文段,其中第一个丢失,第二个到达了B。没有“已失效的连接请求报文段”。
现假定出现一种异常情况,即A发出的第一个连接请求报文段并没有丢失,而是在某些网络结点长时间滞留了,以致延误到连接释放以后的某个时间才到达B。本来这是一个早已失效的报文段。但B收到此失效的连接请求报文段后,就误认为是A又发出一次新的连接请求。于是就向A发出确认报文段,同意建立连接。假定不采用三次握手,那么只要B发出确认,新的连接就建立了。
由于现在A并没有发出建立连接的请求,因此不会理睬B的确认,也不会向B发送数据。但B却以为新的运输连接已经建立了,并一直等待A发来数据。B的许多资源就这样白白浪费了。

问:如果已经建立了连接,但客户端出现了故障怎么办?
答:服务器没收到一次客户端的请求后都会重新复位一个计时器,时间通常是设置为2小时,若两个小时还没有受到客户端的任何数据,服务器会发送一个探测报文段,以后每隔75秒钟发送一次。若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接。

问:初始序列号是什么?
答:TCP连接的一方A,随机选择一个32位(4个字节)的序列号(Sequence Number)作为发送数据的初始序列号(Initial Sequence Number,ISN),比如为1000,以该序列号为原点,对要传送的数据进行编号:1001、1002…三次握手时,把这个初始序列号传送给另一方B,以便在传输数据时,B可以确认什么样的数据编号是合法的;同时在进行数据传输时,A还可以确认B收到的每一个字节,如果A收到了B的确认编号(acknowledge number)是2001,就说明编号为1001-2000的数据已经被B成功接受。

问:A发送给B的确认丢了,该怎么办呢?
答:

  1. 如果第三次握手,有携带数据,那么B需要对A的报文进行确认,如果超时没有收到,A会重传这个确认包;
  2. 如果没有携带数据,那么不会超时重传。B没有收到A的确认包,会超时重传自己的SYN同步信号,一直到收到A的ACK为止。

image.png

理解材料

image.png

https://zhuanlan.zhihu.com/p/86426969