TCP的三次握手和四次握手详解

it2022-05-05  144

http 和 https 请求相信大家都知道的,那么他们是怎样 connect 起来的?又是怎样 close 的呢?答案是先通过三次握手建立 connect 的,然后传输数据,最后通过四次握手 close 的。下面通过一张图先简单了解一下这个过程:

三次握手(建立连接)

作用:

1、确认双方(客户端和服务端)的接受能力和发送能力是否正常

2、指定自己的初始化序列号,会可靠数据传输做准备

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

过程:

建立连接初始时,客户端(client)处于 close 状态,服务端(server)处于 listen(监听)状态,下面先看一张三次握手建立连接图:

具体过程如下:

第一次握手:客户端给服务端发送一个 SYN 报文,并指定客户端的初始化序列号 seq=x ,此时客户端处于 SYN_SENT 状态

第二次握手:服务端收到客户端的 SYN 报文后,给客户端发送了一个自己的 SYN 报文,也指定了服务端的初始化序列号 seq=y,同时将客户端的序列号+1 作为 ACK 的值发送给客户端(表示自己已经收到了客户端的 SYN 报文),此时服务端处于 SYN_RCVD 状态

第三次握手:客户端收到服务端的 SYN 报文后,将服务端的序列号 +1 作为 ACK 的值发送给服务端(表示自己已经收到了服务端的 SYN 报文),此时客户端处于 ESTABLISHED 状态,服务端收到客户端发送的 ACK 报文后,也处于 ESTABLISHED 状态,双方建立起了连接

问题:

1、seq 序列号是固定的吗?

seq 是动态生成的,seq 如果是固定的话,攻击者很容易猜出后续的确认号来进行攻击

2、三次握手过程中可以携带数据吗?

第一次和第二次握手是不可以携带数据的,第三次握手可以。为什么会这样的呢?

第一、二次握手不可以携带数据原因:

你想一下,如果第一次携带数据的话,攻击者不关心服务端是否能正常接收和发送报文,而是直接将大量数据放到报文 SYN 中,这样的话服务端就要花费大量的时间来解析这个报文和大量的内存空间来存储报文,总之一句话就是:第一、二次携带数据更容易让服务端收到恶意攻击

第三次握手可以携带数据原因:

第三次握手时客户端已经处于  ESTABLISHED 状态,而且也知道服务端接收和发送报文能力都是正常的,此时携带数据给服务端完全没有问题

3、什么是半连接队列

第一次握手后,服务端发送报文给客户端后处于 SYN_RCVD 状态,此时客户端和服务端还没有完全建立连接,服务器会将此状态下的请求连接放到一个队列中,我们就将这种队列称之为半连接队列

4、二次握手(SYN + ACK )重传次数

二次握手后,服务端如果没有收到客户端的 ACK 确认报文,就会进行重传。等待一段时间之后如果还没有收到客户端的 ACK 报文,就会进行二次重传,直到等于系统设定的最大重传次数。如果重试次数超过最大重试次数,系统将会把半连接状态的连接从队列中移除。

注意:每次重传等待的时间不一定相同,一般都是指数增长的,例如间隔 1s、2s、8s、16s。。。。。

传输数据过程

建立连接之后自然就是传输数据过程了,整个过程如下图:

超时重传:

超时重传机制用来保证TCP传输的可靠性。每次发送数据包时,发送的数据报都有seq号,接收端收到数据后,会回复ack进行确认,表示某一seq 号数据已经收到。发送方在发送了某个seq包后,等待一段时间,如果没有收到对应的ack回复,就会认为报文丢失,会重传这个数据包。

快速重传:

接受数据一方发现有数据包丢掉了。就会发送ack报文告诉发送端重传丢失的报文。如果发送端连续收到标号相同的ack包,则会触发客户端的快速重传。

超时重传和快速重传区别:超时重传是发送端在傻等超时,然后触发重传;而快速重传则是接收端主动告诉发送端数据没收到,然后触发发送端重传

流量控制:

这里主要说TCP滑动窗流量控制。TCP头里有一个字段叫Window,又叫Advertised-Window,这个字段是接收端告诉发送端自己 还有多少缓冲区可以接收数据。于是发送端就可以根据这个接收端的处理能力来发送数据,而不会导致接收端处理不过来。 滑动窗可以是提高TCP传输效率的一种机制。

拥塞控制:

流量控制和拥塞控制区别:流量控制只关注发送端和接受端自身的状况,而没有考虑整个网络的通信情况。拥塞控制,则是基于整个网络来考虑的

考虑一下这样的场景:某一时刻网络上的延时突然增加,那么,TCP对这个事做出的应对只有重传数据,但是,重传会导致网络的负担更重,于是会导致更大的延迟以及更多 的丢包,于是,这个情况就会进入恶性循环被不断地放大。试想一下,如果一个网络内有成千上万的TCP连接都这么行事,那么马上就会形成“网络风 暴”,TCP这个协议就会拖垮整个网络。为此,TCP引入了拥塞控制策略。拥塞策略算法主要包括:慢启动,拥塞避免,拥塞发生,快速恢复

四次握手(断开连接)

数据传输完之后,网络就需要使用四次握手断开连接了,整个过程如下图:

四次握手断开连接具体过程如下:

第一次握手:客户端发送 FIN 报文给服务端(表示我不再给你发送数据了),报文中指定了序列号 seq=x+2 ,此时客户端处于 FIN_WAIT_1 状态。注意:如果在第一次握手之前发送的数据没有收到服务端的 ACK 确认报文,客户端还会重新这些数据的

第二次握手:服务端收到客户端的 FIN 报文后,发送 ACK 报文给客户端,ACK 报文序列号是客户端序列号+1,即 x+3,此时 服务端处于 CLOSE_WAIT 状态

第三次握手:如果服务端也想断开连接了,就会发送 FIN 报文给客户端(表示我不再给你发送数据了),报文中指定了序列号 seq=y+1,此时服务端处于 LAST_ACK 状态

第四次握手:客户端收到服务端的 FIN 报文后,发送 ACK 报文给服务端,ACK 报文序列号是服务端序列号+1,即 y+2,此时 客户端处于TIME_WAIT 状态。服务端收到客户端的 ACK 报文后,就处于关闭连接状态了,即 CLOSED 状态,而客户端要等一段时间之后以确保服务端收到自己的 ACK 报文之后再关闭连接,即 CLOSED 状态

问题:

1、为什么第四次握手时,客户端发送 ACK 报文给服务端时,不立即处于 CLOSED 状态,而是处于 TIME_WAIT 状态呢?

客户端发送 ACK 报文给服务端后,并不能确保服务端是否已经收到了自己的 ACK 报文,如果没有收到的话,服务端会重新发送 FIN 报文给客户端(请求关闭连接,即第三次握手重试),客户端再次收到服务端的 FIN 报文之后就会知道之前第四次握手发送的 ACK 报文丢失了(服务端没有收到 ACK)。所以客户端需要等待一段时间确保服务端收到了 ACK 之后才能更新成 CLOSED 状态

2、一般 TIME_WAIT 时间是多少呢?

一般 TIME_WAIT 时间至少是一个报文的来回时长。一般会设置一个计时,如果过了这个计时没有再次收到 FIN 报文,则代表对方收到了 ACK 报文,此时可以更新为 CLOSED 状态

各个状态的含义

LISTEN:侦听来自远方 TCP 端口的连接请求。SYN-SENT:在发送连接请求后等待匹配的连接请求。SYN-RECEIVED:在收到和发送一个连接请求后等待对连接请求的确认。ESTABLISHED:代表一个打开的连接,数据可以传送给用户。FIN-WAIT-1:等待远程 TCP 的连接中断请求,或先前的连接中断请求的确认。FIN-WAIT-2:从远程 TCP 等待连接中断请求。CLOSE-WAIT:等待从本地用户发来的连接中断请求。CLOSING:等待远程 TCP 对连接中断的确认。LAST-ACK:等待原来发向远程 TCP 的连接中断请求的确认。TIME-WAIT:等待足够的时间以确保远程 TCP 接收到连接中断请求的确认。CLOSED:没有任何连接状态。

 

 

 

 


最新回复(0)