计算机基础——TCP三次握手四次挥手

发布时间:2024年01月18日

计算机基础——八股文之TCP三次握手四次挥手

一、TCP的三次握手

1.工作原理

假设发送端为客户端,接收端为服务端。开始时客户端和服务端的状态都是close

客户端(Client):用户发送请求(request)的叫客户端

服务端(Server):接收请求做出响应(response)的叫服务端

img

通过抓包得到的数据:

在这里插入图片描述

  1. 第一次握手:客户端向服务端发起建立连接请求,客户端会随机生成一个起始序列号x,客户端向服务端发送的字段中包含标志位SYN=1,序列号:seq=x

    第一次握手前客户端的状态为CLOSE,第一次握手后客户端的状态为SYN-SENT。此时服务端的状态为Listen

  2. 第二次握手:服务端在收到客户端发来的报文后,会随机生成一个服务端的起始序列号y,然后给客户端回复一段报文,其中包括标志位SYN=1ACK=1,序列号seq=y,确认号ack=x+1

    第二次握手前服务端的状态为Listen,第二次握手后服务端的状态为SYN-RCVD,此时客户端的状态为SYN-SENT。(其中SYN=1表示要和客户端建立一个连接,ACK=1表示确认序号有效)

  3. 第三次握手:客户端收到服务端发来的报文后,会再向服务端发送报文,其中包含标志位ACK=1,序列号seq=x+1,确认号ack=y+1

    第三次握手前客户端的状态为SYN-SENT,第三次握手后客户端和服务端的状态都为Established。此时连接建立完成

2.问题

2.1两次握手可以吗?

第三次握手,主要为了防止已失效的连接请求报文段突然又传输到了服务端,导致产生问题

  • 比如客户端A发出连接请求,可能因为网络阻塞原因,A没有收到确认报文,于是A再重传一次连接请求。然后连接成功,等待数据传输完毕后,就释放了连接。然后A发出的第一个连接请求等到连接释放以后的某个时间才到达服务端B,此时B误认为A又发出一次新的连接请求,于是就向A发出确认报文段。
  • 如果不采用三次握手,只要B发出确认,就建立新的连接了,此时A不会响应B的确认且不发送数据,则B一直等待A发送数据,浪费资源

2.2四次握手可以吗?

可以,但是没必要。三次握手是为了确认双方的发送和接收的能力,三次足够解决问题了

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

第三次握手的时候可以携带数据。前两次不能携带数据。

原因:如果前两次握手能够携带数据,那么一旦有人想攻击服务器,那么他只需要在第一次握手中的SYN报文中放大量数据,那么服务器势必会消耗更多的时间和内存空间去处理这些数据,增大了服务器被攻击的风险

第三次握手的时候,客户端已经处于Established状态,并且已经能够确认服务器的接收、发送能力正常,这个时候相对安全了,可以携带数据

二、TCP的四次挥手

1.工作原理

  1. 客户端的应用进程先向其TCP发出连接释放报文段(FIN=1,seq=x),并停止再发送数据,主动关闭TCP连接,进入FIN-WAIT-1(终止等待1)状态,等待服务端的确认

  2. 服务端收到连接释放报文段后即发出确认报文段(ACK=1,ack=x+1,seq=y

    服务端进入CLOSE-WAIT(关闭等待)状态,此时的TCP处于半关闭状态,客户端到服务端的连接释放

  3. 客户端收到服务端的确认后,进入FIN-WAIT-2(终止等待2)状态,等待服务端发出的连接释放报文段

  4. 服务端发送完数据,就会发出连接释放报文段(FIN=1,seq=z,ack=x+1),服务端进入LAST-ACK(最后确认)状态,等待客户端的确认

  5. 客户端收到服务端的连接释放报文段后,对此发出确认报文段(ACK=1,seq=z+1,ack=x+1),客户端进入TIME-WAIT(时间等待)状态。此时TCP为释放掉,需要经过时间等待计时器设置的时间2MSL(最大报文生存时间)后,客户端才进入CLOSE状态。服务端收到客户端发出的确认报文段后关闭连接,若没收到客户端发出的确认报文段,服务端就会重传连接释放报文段

2.问题

2.1第四次挥手为什么要等待2MSL

  1. 保证客户端发送的最后一个ACK报文段能够到达服务端。

    这个ACK报文段有可能丢失,服务端收不到这个确认报文,就会超时重传连接释放报文段,然后客户端可以在2MSL时间内收到这个重传的连接释放报文段,接着客户端重传一次确认,重新启动2MSL计时器,最后客户端和服务端都进入到CLOSE状态

    若客户端在TIME-WAIT状态不等待一段时间,而是发送完ACK报文段后立即释放连接,则无法收到服务端重传的连接释放报文段,所以不会再发送一次确认报文段,服务端就无法正常进入到CLOSE状态

  2. 防止已失效的连接请求报文段出现在本连接中。

    客户端在发送完最后一个ACK报文段后,再经过2MSL,就可以使这个连接所产生的所有报文段都从网络中消失,使下一个新的连接中不会出现旧的连接请求报文段

2.2为什么挥手比握手多一次

因为握手的时候并没有数据传输,所以服务端的SYNACK报文可以一起发送,但是挥手的时候有数据传输,所以ACKFIN报文不能同时发送,需要分两步,所以会比握手多一步

3.3为什么三次挥手不行

因为服务端在接收FIN,往往不会立即返回FIN,必须等到服务端所有的报文都发送完毕了,

才能发FIN。因此先发一个ACK表示已经收到客户端的FIN,延迟一段时间才发FIN。这就造成了四次挥手

如果是三次挥手会造成:
如果将服务端的两次挥手合为一次,等于说服务端将ACK和FIN的发送合并为一次挥手,这个时候长时间的延迟可能会导致客户端误以为FIN没有到达客户端,从而让客户端不断的重发FIN。所有只能第二次握手先发送ACK确认接收到了客户端的数据,等服务器发送完了数据,再发送FIN包进行第三次挥手

三、拓展

1.上文提到的状态名词解析:

  • 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 接收到它的连接终止请求的确认。

    TIME_WAIT 两个存在的理由:
    1.可靠的实现tcp全双工连接的终止
    2.允许老的重复分节在网络中消逝

  • CLOSED:不在连接状态(这是为方便描述假想的状态,实际不存在)

2.TCP报文参数解析:

  • SYN:同步序列号标志位,tcp三次握?中,第?次会将SYN=1,ACK=0,此时表?这是?个连接请求报?段,对?会将SYN=1,ACK=1,表?同意连接,连接完成之后将SYN=0
  • FIN:在tcp四次挥?时第?次将FIN=1,表?此报?段的发送?数据已经发送完毕,这是?个释放链接的标志
  • ACK:当ACK=1时,我们的确认序列号ack才有效,当ACK=0时,确认序号ack?效,TCP规定:所有建?连接的ACK必须全部置为1
  • 序号(seq):占 32位4 个字节,序号范围[0,2^32-1],序号增加到 2^32-1 后,下个序号又回到 0。TCP 是面向字节流的,通过 TCP 传送的字节流中的每个字节都按顺序编号,而报头中的序号字段值则指的是本报文段数据的第一个字节的序号。例如:我们的seq = 201,携带的数据有100,那么最后?个字节的序号就为300,那么下?个报?段就应该从301开始.
    0。TCP 是面向字节流的,通过 TCP 传送的字节流中的每个字节都按顺序编号,而报头中的序号字段值则指的是本报文段数据的第一个字节的序号。例如:我们的seq = 201,携带的数据有100,那么最后?个字节的序号就为300,那么下?个报?段就应该从301开始.
  • 确认号(ack):占 32位4 个字节,期望收到对方下个报文段的第一个数据字节的序号。当标志位ACK值为1时,才能产生有效的确认号ack。并且:ack=seq+1;
文章来源:https://blog.csdn.net/m0_56223760/article/details/135607381
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。