TCP为什么要经过三次握手和四次挥手?

1.为什么要进行三次握手?

大学时期的《计算机网络》一书中说道:

为了防止已经失效的连接请求报文段突然又传到服务端,因而产生错误。

客户端发送到服务端的连接请求报文,由于网络延迟,阻塞等原因,在连接已经释放后被服务端接收到,此时服务端往客户端发送报文表示建立连接。此时会产生2个问题:

1.建立很多无效的连接,浪费资源;

2.客户端收到来自服务端的报文后,还需要再次发送确认报文来建立连接。

1.1.先讲一下握手过程中的重要标志位

  • SYN(synchronous):在建立连接时用来同步序号。当SYN=1而ACK=0时,表明这是一个连接请求报文。对方若同意建立连接,则应在响应报文中使SYN=1和ACK=1。因此,SYN=1表示这是一个连接请求或者连接接受报文。

  • Seq(Sequence number):初始化序列号。在TCP传输中,每一个字节都是有序号的,从0开始,通过序号的方式保存数据的顺序,接收端在接收到后进行重新排列成需要的数据。

  • ACK(Acknowledge number):TCP协议规定,只有ACK=1时有效,也规定连接建立后所有发送的报文的ACK必须为1。

  • FIN(finish):结束,用来释放一个连接。当FIN=1时,表明此报文段发送方的数据已经发送完毕,并要求释放连接。

1.2 三次握手过程

三次握手过程

第一次握手:建立连接。客户端发送连接请求,将SYN置为1,Sequence Number = x。然后服务器进入SYN_SEND状态,等待服务器的确认。

第二次握手:服务器收到SYN报文段。收到客户端发送的报文段,需要对这个SYN进行确认,设置ACK(Acknowledgment Number) 为x + 1(Sequence Number+1)。同时,服务器发送SYN请求信息,SYN置为1,Sequence Number 为y,服务器端将上述所有信息放到一个报文段(ACK+SYN)中,一并发给客户端,此时服务器状态置为SYN_RECEV状态。

第三次握手:客户端收到服务器的SYN+ACK报文段。然后将Ack设置为y+1,向服务器发送ACK报文段,报文段发送完毕后,客户端和服务端都进入ESTABLISHED状态,完成TCP三次握手。

为什么是三次握手?

为什么是3次握手,2次或4次不好吗? 那我们就从结果逆向推导,来证明2次太少,4次又没必要。

握手的本质,就是要建立连接,确保客户端和服务端的发送和接收能力都没有问题。客户端要确认发送端的接收和发送能力没有问题,服务端同样要确认客户端发送和接收能力没有问题。

第一次握手:客户端发送连接请求到服务端,服务端接收确认,服务端确定客户端发送能力ok;

第二次握手:服务端向客户端发送确认接受报文,客户端接收到服务端的SYN+ACK报文,确定服务端的接收和发送能力ok。那握手到此结束可以了吧? 然而客户端并不能确定客户端的接收能力有没有问题。

第三次握手:客户端向服务端发送报文,服务端接收到报文后,确定客户端接收能力ok,连接建立成功。

这里补充两个知识点:

1.Seq和Ack的关系是怎样的?

Seq表示发送的这个包中的第一个字节的序号;Ack表示已成功接收到序号到Ack-1的数据,期望接收的下一个字节的序号为Ack。

举个栗子:

假如前面已经发送了100字节的数据,那么下一个发送的包中的Seq从101开始,比如这个包包含10字节,那么字节编号就是101-110.之后继续发送的话,序号从111开始。而接收端在接收这10个字节后,便返回一个Ack=111的包,表示已经接收到101-110序号的字节,期望下一个接收到的字节从111开始。

在握手过程中,Ack = Seq + 1,因为请求连接建立时发送了1字节请求数据。

2.TCP状态都有哪些?

  • LISTEN:监听来自其他主机的TCP端口的请求;

  • SYN_SEND: 发送连接请求后,等待确认连接请求;

  • SYN-RECEIVED:收到连接请求后,等待确认建立连接请求;

  • ESTABLISHED: 表示连接已经建立起来,可以进行数据传输了;

  • FIN_WAIT_1: 等待远程TCP连接中断请求或者先前的中断请求的确认;

  • FIN_WAIT_1:等待来自远程TCP连接的中断请求;

  • CLOSE_WAIT:该端点已经收到远程端点的终端请求,等待本地应用程序连接中断请求;

  • CLOSING:等待来自远程TCP的终止请求的确认;

  • LAST_ACK:等待之前发送到远程TCP的连接终止请求的确认;

  • TIME_WAIT:等待足够的时间确保远程TCP接收连接中断请求的确认;

  • CLOSED:没有任何连接状态;

2.四次挥手

2.1四次挥手过程

四次挥手

1.第一次挥手:主机1(可以是客户端,也可以是服务端),设置Seq和Ack,向主机2发送一个FIN报文段。此时主机1进入FIN_WAIT_1状态,表示主机1没有数据要发送给主机2了;

2.第二次挥手:主机2收到了主机1发送的FIN报文段,向主机1发送了一个Ack报文段,Ack = Seq + 1;主机1进入FIN_WAIT_2状态;主机2告诉主机1,我”同意“你的关闭请求:

3.第三次挥手:主机2向主机1发送FIN报文段,请求关闭连接,同时主机2进入LAST_ACK状态;

4.第四次挥手:主机1收到主机2发送的FIN报文段,向主机2发送Ack报文段,然后主机1进入TIME_WAIT状态;主机2收到主机1的Ack报文段以后,就关闭连接。主机1在等待2MSL后依然没有收到回复,则证明Server端已经正常关闭。然后,主机1也关闭连接。

四次挥手是因为TCP是全双工模式,接收到FIN时,意味着没有数据再发来,但是可以继续发送数据。

3.面试题问题重点

3.1 客户端发送ACK之后为什么不直接关闭,而是要等上一段时间才关闭?

原因是确保服务器是否已经收到了客户端发送的ACK报文,如果没有收到的话,服务端会重发FIN报文给客户端,客户端再次收到FIN报文,知道之前发送的ACK报文丢失了,然后再次发送ACK报文给服务端。

TIME_WAIT持续的时间至少是一个报文的来回时间。如果过了这个时间没有收到FIN报文,表示对方已经成功接收,并处于CLOSED状态。

3.2 三次握手的作用

1.确定双方的发送和接收能力正常。

2.指定自己的初始化序列号,为可靠通信做准备。

3.如果是https协议的话,三次握手过程,还会进行数字证书验证和会话密钥的生成。

3.3 Sequence Number是固定的吗?

三次握手的一个重要功能是客户端和服务端交换ISN(Initial Sequence Number),以便让对方知道接下来接收数据时如何按照序列号组装数据。如果Sequence Number是固定的,很容易让攻击者猜出后续的确认号,因此,Sequence Number是动态生成的。

3.4 什么是半连接队列?

服务器第一次收到SYN报文后,会处于SYN_RECEIVED状态,此时双方还没有完全建立连接,服务器会把此种状态下请求连接放在一个队列里,我们把这种队列称之为半连接队列。还有全连接队列,就是已经完成三次握手,建立起连接的就会放入全连接队列,如果队列满了,可能会出现丢包的现象。

3.5 服务端SYN-ACK重传机制

服务器在发送完SYN+ACK报文后,如果没有收到客户端的确认报,就会进行首次重传。如果等待一段时间后,仍然没有收到客户端的确认报,会进行第二次重传。如果重传次数超过系统规定的最大重传次数,则系统将该连接信息从半连接队列中删除。值得注意的是,每次重传等待时间一般呈指数级增长,2s,4s,8s,16s...

你可能感兴趣的:(TCP为什么要经过三次握手和四次挥手?)