快捷搜索:  汽车  科技

为什么tcp需要三次握手四次挥手?讲讲TCP的3次握手和4次挥手

为什么tcp需要三次握手四次挥手?讲讲TCP的3次握手和4次挥手3次已经足够了,4次也可以,但是连接的速度比3次慢,没有好处。TCP是双工的,需要确认双方传输数据链路通畅,如果是2次,只能说明客户端上传数据到服务端链路是OK的,不能说明服务端下发数据给客户端链路是OK的。(3)请求方-ACK包。客户端接收到来自服务器端的确认收到数据的TCP报文之后,明确了从客户端到服务器的数据传输是正常的,结束SYN-SENT阶段。并返回最后一段TCP报文。其中:(4)服务器收到来自客户端的“确认收到服务器数据”的TCP报文之后,明确了从服务器到客户端的数据传输是正常的。结束SYN-SENT阶段,进入ESTABLISHED阶段。在客户端与服务器端传输的TCP报文中,双方的确认号ack和序号seq的值,都是在彼此ack和seq值的基础上进行计算的,这样做保证了TCP报文传输的连贯性。一旦出现某一方发出的TCP报文丢失,便无法继续"握手",以此确保了

TCP的3次握手和4次挥手

如果涉及网络,必然会考TCP/IP,而切入的话题就是“3次握手和4次挥手”。

3次握手

为什么tcp需要三次握手四次挥手?讲讲TCP的3次握手和4次挥手(1)

握手之前主动打开连接的客户端结束CLOSED阶段,被动打开的服务器端也结束CLOSED阶段,并进入LISTEN阶段。随后开始“三次握手”:

(1)请求方-SYN包。首先客户端向服务器端发送一段TCP报文,其中:

  • 标记位为SYN,表示“请求建立新连接”;
  • 序号为seq=x(x一般为1);
  • 随后客户端进入SYN-SENT阶段。

(2)接收方-SYNACK包。服务器端接收到来自客户端的TCP报文之后,结束LISTEN阶段。并返回一段TCP报文,其中:

  • 标志位为SYN和ACK,表示“确认客户端的报文seq序号有效,服务器能正常接收客户端发送的数据,并同意创建新连接”(即告诉客户端,服务器收到了你的数据);
  • 序号为seq=y;
  • 确认号为ack=x 1,表示收到客户端的序号seq并将其值加1作为自己确认号ack的值;随后服务器端进入SYN-RCVD阶段。

(3)请求方-ACK包。客户端接收到来自服务器端的确认收到数据的TCP报文之后,明确了从客户端到服务器的数据传输是正常的,结束SYN-SENT阶段。并返回最后一段TCP报文。其中:

  • 标志位为ACK,表示“确认收到服务器端同意连接的信号”(即告诉服务器,我知道你收到我发的数据了);
  • 序号为seq=x 1,表示收到服务器端的确认号ack,并将其值作为自己的序号值;
  • 确认号为ack=y 1,表示收到服务器端序号seq,并将其值加1作为自己的确认号ack的值;随后客户端进入ESTABLISHED阶段。

(4)服务器收到来自客户端的“确认收到服务器数据”的TCP报文之后,明确了从服务器到客户端的数据传输是正常的。结束SYN-SENT阶段,进入ESTABLISHED阶段。

在客户端与服务器端传输的TCP报文中,双方的确认号ack和序号seq的值,都是在彼此ack和seq值的基础上进行计算的,这样做保证了TCP报文传输的连贯性。一旦出现某一方发出的TCP报文丢失,便无法继续"握手",以此确保了"三次握手"的顺利完成。此后客户端和服务器端进行正常的数据传输。这就是“三次握手”的过程。

面试题1:为什么不是2次或4次

TCP是双工的,需要确认双方传输数据链路通畅,如果是2次,只能说明客户端上传数据到服务端链路是OK的,不能说明服务端下发数据给客户端链路是OK的。

3次已经足够了,4次也可以,但是连接的速度比3次慢,没有好处。

面试题2:半连接攻击是什么,如何防范?

(1)半连接:握手阶段,服务器“收到SYNACK包之后,收到客户端ACK包之前”的TCP连接。服务器维护一个队列,存放半连接,保存seq值和连接的关系,称之为半连接队列Backlog是半连接队列的最大容纳数目。

(2)半连接攻击:发送伪造的大量SYN包,并不发送ACK包,让服务器产生大量半连接,半连接队列满后,正常连接就无法连入了。

(3)防范:

  • 利用SYN Cookie。当半连接队列满后,服务器不拒绝新的SYN请求,而是收到SYN请求时,对客户端IP地址、端口、服务器IP地址、端口及其他安全要素,计算出一个hash值,把这个cookie作为SYNACK的seq序号发回客户端。如果客户端回复了ACK包,将ack-1,就得到了发送出去的seq序号,然后再次利用那些安全要素计算哈希值,如果两个值相等,说明已经正常完成了3次握手,直接建立连接即可。
  • 其他方法:扩展队列大小、减少服务器超时时间。
4次挥手

为什么tcp需要三次握手四次挥手?讲讲TCP的3次握手和4次挥手(2)

(1)请求方-FIN包。首先客户端想要释放连接,向服务器端发送一段TCP报文,其中:

  • 标记位为FIN,表示“请求释放连接“;
  • 序号为seq=u;
  • 随后客户端进入FIN-WAIT-1阶段,即半关闭阶段。并且停止在客户端到服务器端方向上发送数据报文(但可以发送ACK),但是客户端仍然能接收从服务器端传输过来的数据。

(2)接收方-ACK包。服务器端接收到从客户端发出的TCP报文之后,确认了客户端想要释放连接,随后服务器端结束ESTABLISHED阶段,进入CLOSE-WAIT阶段(半关闭状态)并返回一段TCP报文,其中:

  • 标记位为ACK,表示“接收到客户端发送的释放连接的请求”;
  • 序号为seq=v;
  • 确认号为ack=u 1,表示是在收到客户端报文的基础上,将其序号seq值加1作为本段报文确认号ack的值;

客户端收到服务端的ACK报文,进入FIN-WAIT-2阶段,等待服务器传完数据。随后服务器端开始准备释放服务器端到客户端方向上的连接,期间把剩余未传输完毕的数据继续传完。

(3)接收方-FIN-ACK包。服务器端把剩余数据传完后,再次向客户端发出一段TCP报文,其中:

  • 标记位为FIN,ACK,表示“已经准备好释放连接了”。注意:这里的ACK并不是确认收到服务器端报文的确认报文。
  • 序号为seq=w(因为中间传了一些数据,w不一定和v是连续的)
  • 确认号为ack=u 1;表示是在收到客户端报文的基础上,将其序号seq值加1作为本段报文确认号ack的值。

随后服务器端结束CLOSE-WAIT阶段,进入LAST-ACK阶段。并且停止在服务器端到客户端的方向上发送数据,但是服务器端仍然能够接收从客户端传输过来的数据。

(4)请求方-ACK包。客户端收到从服务器端发出的TCP报文,确认了服务器端已做好释放连接的准备,进入TIME-WAIT阶段,并向服务器端发送一段报文,其中:

  • 标记位为ACK,表示“接收到服务器准备好释放连接的信号”。
  • 序号为seq=u 1;表示是在收到了服务器端报文的基础上,将其确认号ack值作为本段报文序号的值。
  • 确认号为ack=w 1;表示是在收到了服务器端报文的基础上,将其序号seq值作为本段报文确认号的值。

随后客户端开始在TIME-WAIT阶段等待2MSL(Maximum Segment Lifetime,最大分段生成期,TCP报文在Internet上最长生存时间,默认2分钟)

加分:但实际上Linux对TIME-WAIT的等待时间默认实现的是60秒

(5)服务器端收到从客户端发出的TCP报文之后结束LAST-ACK阶段,进入CLOSED阶段。由此正式确认关闭服务器端到客户端方向上的连接。

(6)客户端等待完2MSL之后,结束TIME-WAIT阶段,进入CLOSED阶段,由此完成“四次挥手”。

面试题3:为什么握手是3次,挥手却要4次?

因为挥手不能立刻断开连接,要等数据发完。

  • 建立连接时,被动方服务器端结束CLOSED阶段进入“握手”阶段并不需要任何准备,可以直接返回SYN和ACK报文,开始建立连接。
  • 释放连接时,被动方服务器,突然收到主动方客户端释放连接的请求时并不能立即释放连接,因为还有必要的数据需要处理,所以服务器先返回ACK确认收到报文,经过CLOSE-WAIT阶段准备好释放连接之后,才能返回FIN释放连接报文
面试题4:为什么客户端在TIME-WAIT阶段要等待2MSL?

为的是确认服务器端已经收到客户端发出的ACK确认报文。假设客户端ACK包丢了,连接断开了,客户端没机会重传了。所以需要等待一段时间。

这个时间为什么是2MSL,是因为如果服务器端在1MSL内没有收到客户端发出的ACK确认报文,就会再次向客户端发出FINACK报文;如果此时客户端收到了新的FIN报文,则需要重新ACK,并重新计时2MSL。

面试题5:如果FIN-WAIT-2阶段没有收到服务端的报文,怎么办?

如果没收到服务端FINACK:

  • TCP标准规定是,一直等待在FIN-WAIT-2阶段
  • 实际上Linux2.2以上会设置超时时间tcp_fin_timeout=60s,连接会被强行关闭
面试题6:发现服务端出现了大量FIN-WAIT-1阶段的连接,是什么情况,如何处理?

注意这里是服务器,不是服务端,出现FIN-WAIT-1,说明是服务端主动想关闭连接,于是向客户端发送了这个请求。

处于FIN-WAIT-1,说明发送了FIN包,但是没有收到ACK包,很可能链路出现了问题,FIN包被丢弃了,或者ACK包传不回来。于是服务端会不断重试发送FIN包,默认重试次数是8次,指数时间退避,这个时间会非常长,如果大量TCP都在重试,就会都处于FIN-WAIT-1阶段。我们可以把这个重试次数改小,让它尽快结束FIN-WAIT-1阶段。

面试题7:发现服务端出现了大量TIME-WAIT的连接,是什么情况,如何处理?

和前面一样,当服务端需要主动关闭连接时候,才会出现TIME-WAIT的情况。

大量未关闭连接,会占用内存、文件描述符等资源。

(1)开启net.ipv4.tcp_tw_reuse,让处于time-wait状态的连接能够被重用

(2)开启net.ipv4.tcp_tw_recycle,减少time-wait的等待时间,从2MSL减少为1RTO(Retransmission Timeout,数据包重传超时时间,约为0.7s)

结束语

能看到这里的你,一定是个热爱编程的同学。如果想要有计划地准备大厂面试,欢迎关注。

关注我,带你像准备高考一样有计划地准备大厂面试!(当前:2022年第7周)

周一:新闻动态——了解岗位要求、薪资,找到目标

周二:编程刷题——高频算法面试题

周三:专业真题——高频连环炮提问

周四:面试提问——HR面的问题如何回答

周五:热门推荐——高效工具

猜您喜欢: