[转]面试官,不要再问我三次握手和四次挥手

 

 

文章目录

    • 1. 三次握手
      • 1.1 为什么需要三次握手,两次不行吗?
      • 1.2 什么是半连接队列?
      • 1.3 ISN(Initial Sequence Number)是固定的吗?
      • 1.4 三次握手过程中可以携带数据吗?
      • 1.5 SYN攻击是什么?
    • 2. 四次挥手
      • 2.1 挥手为什么需要四次?
      • 2.2 2MSL等待状态
      • 2.3 四次挥手释放连接时,等待2MSL的意义?
        • 两个理由:
      • 2.4 为什么TIME_WAIT状态需要经过2MSL才能返回到CLOSE状态?
    • 3. 总结


三次握手和四次挥手是各个公司常见的考点,也具有一定的水平区分度,也被一些面试官作为热身题。很多小伙伴说这个问题刚开始回答的挺好,但是后面越回答越冒冷汗,最后就歇菜了。

 

 

见过比较典型的面试场景是这样的:

 

面试官:请介绍下三次握手
求职者:第一次握手就是客户端给服务器端发送一个报文,第二次就是服务器收到报文之后,会应答一个报文给客户端,第三次握手就是客户端收到报文后再给服务器发送一个报文,三次握手就成功了。
面试官:然后呢?
求职者:这就是三次握手的过程,很简单的。
面试官:。。。。。。
番外篇:一首凉凉送给你

 

记住猿人谷一句话:面试时越简单的问题,一般就是隐藏着比较大的坑,一般都是需要将问题扩展的。上面求职者的回答不对吗?当然对,但距离面试官的期望可能还有点距离。

 

希望大家能带着如下问题进行阅读,收获会更大。

 

  1. 请画出三次握手和四次挥手的示意图
  2. 为什么连接的时候是三次握手?
  3. 什么是半连接队列?
  4. ISN(Initial Sequence Number)是固定的吗?
  5. 三次握手过程中可以携带数据吗?
  6. 如果第三次握手丢失了,客户端服务端会如何处理?
  7. SYN攻击是什么?
  8. 挥手为什么需要四次?
  9. 四次挥手释放连接时,等待2MSL的意义?

 

三次握手和四次挥手.png

 

1. 三次握手

 

三次握手(Three-way Handshake)其实就是指建立一个TCP连接时,需要客户端和服务器总共发送3个包。进行三次握手的主要作用就是为了确认双方的接收能力和发送能力是否正常、指定自己的初始化序列号为后面的可靠性传送做准备。实质上其实就是连接服务器指定端口,建立TCP连接,并同步连接双方的序列号和确认号,交换TCP窗口大小信息。

 

刚开始客户端处于 Closed 的状态,服务端处于 Listen 状态。
进行三次握手:

 

  • 第一次握手:客户端给服务端发一个 SYN 报文,并指明客户端的初始化序列号 ISN©。此时客户端处于 SYN_SEND 状态。

    首部的同步位SYN=1,初始序号seq=x,SYN=1的报文段不能携带数据,但要消耗掉一个序号。

  • 第二次握手:服务器收到客户端的 SYN 报文之后,会以自己的 SYN 报文作为应答,并且也是指定了自己的初始化序列号 ISN(s)。同时会把客户端的 ISN + 1 作为ACK 的值,表示自己已经收到了客户端的 SYN,此时服务器处于 SYN_REVD 的状态。

    在确认报文段中SYN=1,ACK=1,确认号ack=x+1,初始序号seq=y。

  • 第三次握手:客户端收到 SYN 报文之后,会发送一个 ACK 报文,当然,也是一样把服务器的 ISN + 1 作为 ACK 的值,表示已经收到了服务端的 SYN 报文,此时客户端处于 ESTABLISHED 状态。服务器收到 ACK 报文之后,也处于 ESTABLISHED 状态,此时,双方已建立起了连接。

    确认报文段ACK=1,确认号ack=y+1,序号seq=x+1(初始为seq=x,第二个报文段所以要+1),ACK报文段可以携带数据,不携带数据则不消耗序号。

 

发送第一个SYN的一端将执行主动打开(active open),接收这个SYN并发回下一个SYN的另一端执行被动打开(passive open)。

 

在socket编程中,客户端执行connect()时,将触发三次握手。

 

三次握手.png

 

1.1 为什么需要三次握手,两次不行吗?

 

弄清这个问题,我们需要先弄明白三次握手的目的是什么,能不能只用两次握手来达到同样的目的。

 

  • 第一次握手:客户端发送网络包,服务端收到了。
    这样服务端就能得出结论:客户端的发送能力、服务端的接收能力是正常的。
  • 第二次握手:服务端发包,客户端收到了。
    这样客户端就能得出结论:服务端的接收、发送能力,客户端的接收、发送能力是正常的。不过此时服务器并不能确认客户端的接收能力是否正常。
  • 第三次握手:客户端发包,服务端收到了。
    这样服务端就能得出结论:客户端的接收、发送能力正常,服务器自己的发送、接收能力也正常。

 

因此,需要三次握手才能确认双方的接收与发送能力是否正常。

 

试想如果是用两次握手,则会出现下面这种情况:

 

如客户端发出连接请求,但因连接请求报文丢失而未收到确认,于是客户端再重传一次连接请求。后来收到了确认,建立了连接。数据传输完毕后,就释放了连接,客户端共发出了两个连接请求报文段,其中第一个丢失,第二个到达了服务端,但是第一个丢失的报文段只是在某些网络结点长时间滞留了,延误到连接释放以后的某个时间才到达服务端,此时服务端误认为客户端又发出一次新的连接请求,于是就向客户端发出确认报文段,同意建立连接,不采用三次握手,只要服务端发出确认,就建立新的连接了,此时客户端忽略服务端发来的确认,也不发送数据,则服务端一致等待客户端发送数据,浪费资源。

 

1.2 什么是半连接队列?

 

服务器第一次收到客户端的 SYN 之后,就会处于 SYN_RCVD 状态,此时双方还没有完全建立其连接,服务器会把此种状态下请求连接放在一个队列里,我们把这种队列称之为半连接队列

 

当然还有一个全连接队列,就是已经完成三次握手,建立起连接的就会放在全连接队列中。如果队列满了就有可能会出现丢包现象。

 

这里在补充一点关于SYN-ACK 重传次数的问题:
服务器发送完SYN-ACK包,如果未收到客户确认包,服务器进行首次重传,等待一段时间仍未收到客户确认包,进行第二次重传。如果重传次数超过系统规定的最大重传次数,系统将该连接信息从半连接队列中删除。
注意,每次重传等待的时间不一定相同,一般会是指数增长,例如间隔时间为 1s,2s,4s,8s…

 

1.3 ISN(Initial Sequence Number)是固定的吗?

 

当一端为建立连接而发送它的SYN时,它为连接选择一个初始序号。ISN随时间而变化,因此每个连接都将具有不同的ISN。ISN可以看作是一个32比特的计数器,每4ms加1 。这样选择序号的目的在于防止在网络中被延迟的分组在以后又被传送,而导致某个连接的一方对它做错误的解释。

 

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

 

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

 

其实第三次握手的时候,是可以携带数据的。但是,第一次、第二次握手不可以携带数据

 

为什么这样呢?大家可以想一个问题,假如第一次握手可以携带数据的话,如果有人要恶意攻击服务器,那他每次都在第一次握手中的 SYN 报文中放入大量的数据。因为攻击者根本就不理服务器的接收、发送能力是否正常,然后疯狂着重复发 SYN 报文的话,这会让服务器花费很多时间、内存空间来接收这些报文。

 

也就是说,第一次握手不可以放数据,其中一个简单的原因就是会让服务器更加容易受到攻击了。而对于第三次的话,此时客户端已经处于 ESTABLISHED 状态。对于客户端来说,他已经建立起连接了,并且也已经知道服务器的接收、发送能力是正常的了,所以能携带数据也没啥毛病。

 

1.5 SYN攻击是什么?

 

服务器端的资源分配是在二次握手时分配的,而客户端的资源是在完成三次握手时分配的,所以服务器容易受到SYN洪泛攻击。SYN攻击就是Client在短时间内伪造大量不存在的IP地址,并向Server不断地发送SYN包,Server则回复确认包,并等待Client确认,由于源地址不存在,因此Server需要不断重发直至超时,这些伪造的SYN包将长时间占用未连接队列,导致正常的SYN请求因为队列满而被丢弃,从而引起网络拥塞甚至系统瘫痪。SYN 攻击是一种典型的 DoS/DDoS 攻击。

 

检测 SYN 攻击非常的方便,当你在服务器上看到大量的半连接状态时,特别是源IP地址是随机的,基本上可以断定这是一次SYN攻击。在 Linux/Unix 上可以使用系统自带的 netstats 命令来检测 SYN 攻击。

 

netstat -n -p TCP | grep SYN_RECV

 

常见的防御 SYN 攻击的方法有如下几种:

 

  • 缩短超时(SYN Timeout)时间
  • 增加最大半连接数
  • 过滤网关防护
  • SYN cookies技术

 

2. 四次挥手

 

建立一个连接需要三次握手,而终止一个连接要经过四次挥手(也有将四次挥手叫做四次握手的)。这由TCP的半关闭(half-close)造成的。所谓的半关闭,其实就是TCP提供了连接的一端在结束它的发送后还能接收来自另一端数据的能力。

 

TCP 的连接的拆除需要发送四个包,因此称为四次挥手(Four-way handshake),客户端或服务器均可主动发起挥手动作。

 

刚开始双方都处于 ESTABLISHED 状态,假如是客户端先发起关闭请求。四次挥手的过程如下:

 

  • 第一次挥手:客户端发送一个 FIN 报文,报文中会指定一个序列号。此时客户端处于 FIN_WAIT1 状态。
    即发出连接释放报文段(FIN=1,序号seq=u),并停止再发送数据,主动关闭TCP连接,进入FIN_WAIT1(终止等待1)状态,等待服务端的确认。
  • 第二次挥手:服务端收到 FIN 之后,会发送 ACK 报文,且把客户端的序列号值 +1 作为 ACK 报文的序列号值,表明已经收到客户端的报文了,此时服务端处于 CLOSE_WAIT 状态。
    即服务端收到连接释放报文段后即发出确认报文段(ACK=1,确认号ack=u+1,序号seq=v),服务端进入CLOSE_WAIT(关闭等待)状态,此时的TCP处于半关闭状态,客户端到服务端的连接释放。客户端收到服务端的确认后,进入FIN_WAIT2(终止等待2)状态,等待服务端发出的连接释放报文段。
  • 第三次挥手:如果服务端也想断开连接了,和客户端的第一次挥手一样,发给 FIN 报文,且指定一个序列号。此时服务端处于 LAST_ACK 的状态。
    即服务端没有要向客户端发出的数据,服务端发出连接释放报文段(FIN=1,ACK=1,序号seq=w,确认号ack=u+1),服务端进入LAST_ACK(最后确认)状态,等待客户端的确认。
  • 第四次挥手:客户端收到 FIN 之后,一样发送一个 ACK 报文作为应答,且把服务端的序列号值 +1 作为自己 ACK 报文的序列号值,此时客户端处于 TIME_WAIT 状态。需要过一阵子以确保服务端收到自己的 ACK 报文之后才会进入 CLOSED 状态,服务端收到 ACK 报文之后,就处于关闭连接了,处于 CLOSED 状态。
    即客户端收到服务端的连接释放报文段后,对此发出确认报文段(ACK=1,seq=u+1,ack=w+1),客户端进入TIME_WAIT(时间等待)状态。此时TCP未释放掉,需要经过时间等待计时器设置的时间2MSL后,客户端才进入CLOSED状态。

 

收到一个FIN只意味着在这一方向上没有数据流动。客户端执行主动关闭并进入TIME_WAIT是正常的,服务端通常执行被动关闭,不会进入TIME_WAIT状态。

 

在socket编程中,任何一方执行close()操作即可产生挥手操作。
image.png

 

2.1 挥手为什么需要四次?

 

因为当服务端收到客户端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当服务端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉客户端,“你发的FIN报文我收到了”。只有等到我服务端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四次挥手。

 

2.2 2MSL等待状态

 

TIME_WAIT状态也成为2MSL等待状态。每个具体TCP实现必须选择一个报文段最大生存时间MSL(Maximum Segment Lifetime),它是任何报文段被丢弃前在网络内的最长时间。这个时间是有限的,因为TCP报文段以IP数据报在网络内传输,而IP数据报则有限制其生存时间的TTL字段。

 

对一个具体实现所给定的MSL值,处理的原则是:当TCP执行一个主动关闭,并发回最后一个ACK,该连接必须在TIME_WAIT状态停留的时间为2倍的MSL。这样可让TCP再次发送最后的ACK以防这个ACK丢失(另一端超时并重发最后的FIN)。

 

这种2MSL等待的另一个结果是这个TCP连接在2MSL等待期间,定义这个连接的插口(客户的IP地址和端口号,服务器的IP地址和端口号)不能再被使用。这个连接只能在2MSL结束后才能再被使用。

 

2.3 四次挥手释放连接时,等待2MSL的意义?

 

MSL是Maximum Segment Lifetime的英文缩写,可译为“最长报文段寿命”,它是任何报文在网络上存在的最长时间,超过这个时间报文将被丢弃。

 

为了保证客户端发送的最后一个ACK报文段能够到达服务器。因为这个ACK有可能丢失,从而导致处在LAST-ACK状态的服务器收不到对FIN-ACK的确认报文。服务器会超时重传这个FIN-ACK,接着客户端再重传一次确认,重新启动时间等待计时器。最后客户端和服务器都能正常的关闭。假设客户端不等待2MSL,而是在发送完ACK之后直接释放关闭,一但这个ACK丢失的话,服务器就无法正常的进入关闭连接状态。

 

两个理由:

 

  1. 保证客户端发送的最后一个ACK报文段能够到达服务端。
    这个ACK报文段有可能丢失,使得处于LAST-ACK状态的B收不到对已发送的FIN+ACK报文段的确认,服务端超时重传FIN+ACK报文段,而客户端能在2MSL时间内收到这个重传的FIN+ACK报文段,接着客户端重传一次确认,重新启动2MSL计时器,最后客户端和服务端都进入到CLOSED状态,若客户端在TIME-WAIT状态不等待一段时间,而是发送完ACK报文段后立即释放连接,则无法收到服务端重传的FIN+ACK报文段,所以不会再发送一次确认报文段,则服务端无法正常进入到CLOSED状态。
  2. 防止“已失效的连接请求报文段”出现在本连接中。
    客户端在发送完最后一个ACK报文段后,再经过2MSL,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失,使下一个新的连接中不会出现这种旧的连接请求报文段。

 

2.4 为什么TIME_WAIT状态需要经过2MSL才能返回到CLOSE状态?

 

理论上,四个报文都发送完毕,就可以直接进入CLOSE状态了,但是可能网络是不可靠的,有可能最后一个ACK丢失。所以TIME_WAIT状态就是用来重发可能丢失的ACK报文

 

3. 总结

 

《TCP/IP详解 卷1:协议》有一张TCP状态变迁图,很具有代表性,有助于大家理解三次握手和四次挥手的状态变化。如下图所示,粗的实线箭头表示正常的客户端状态变迁,粗的虚线箭头表示正常的服务器状态变迁。

 

TCP状态变迁图.jpg

 

以后面试官再问你三次握手和四次挥手,直接把这一篇文章丢给他就可以了,他想问的都在这里。

 

参考:《TCP/IP详解 卷1:协议》


---------------------
作者:夏雪冬日
来源:CSDN
原文:https://blog.csdn.net/hyg0811/article/details/102366854
版权声明:本文为作者原创文章,转载请附上博文链接!
内容解析By:CSDN,CNBLOG博客文章一键转载插件

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/285474.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C语言试题115之两个乒乓球队进行比赛,各出三人。甲队为 a,b,c 三人,乙队为 x,y,z 三人。已抽签决定 比赛名单。有人向队员打听比赛的名单。a 说他不和 x 比,c 说他不和 x,z 比,请

✅作者简介:大家好我是码莎拉蒂,CSDN博客专家🥇🥇🥇 📃个人主页:个人主页 🔥系列专栏:C语言试题200例 💬推荐一款模拟面试、刷题神器👉 点击跳转进入网站 1、题目 题目:两个乒乓球队进行比赛,各出三人。甲队为 a,b,c 三人,乙队为 x,y,z 三人。已抽签决定…

(04).NET MAUI实战 MVVM

1.概要本章将讲解如何在MAUI中使用简单的MVVM模式开发“ListView”内容的增删功能,MVVM在MAUI中也同样适用。Microsoft.Toolkit.Mvvm在学习之前我们先了解一个nuget包,它可以帮助我们省去一些代码的开发时间。包Microsoft.Toolkit.Mvvm (aka MVVM Toolki…

WTM重大更新,多租户和单点登录

WTM重大更新多租户单点登录随着WTM被越来越多地应用于企业,用户对于多租户和单点登录的需求越来越强烈。经过了几个月的努力,我们把WTM底层代码又进行了一次优化和重构,加入了多租户和单点登录的功能。VUE,Blazor,LayU…

struts2注解

2019独角兽企业重金招聘Python工程师标准>>> 以下均为本人工作中的笔记内容,不够全面具体。碰到什么我就记录什么,只是作为笔记使用,希望大家多提宝贵意见,共同进步。Action("login"):定义action //或者写…

[转]H5直播之从推流服务搭建到视频直播

转自http://www.php.cn/html5-tutorial-403035.html 最近视频直播比较火,发现目前 WEB 上主流的视频直播方案有 HLS 和 RTMP,移动 WEB 端目前以 HLS 为主,PC端则以 RTMP 为主实时性较好,接下来将围绕这两种视频流协议来展开H5直播…

webform数据导出

把数据放到一个泛型集合里,再把泛型集合里面的数据放到一个table中,设置好文件路径,然后进行文件读取,最后供用户下载。 数据导出放在一个按钮中就可以了 using System; using System.Collections.Generic; using System.Linq; us…

C语言试题117之有一分数序列:2/1,3/2,5/3,8/5,13/8,21/13...求出这个数列的前 20 项之和

✅作者简介:大家好我是码莎拉蒂,CSDN博客专家🥇🥇🥇 📃个人主页:个人主页 🔥系列专栏:C语言试题200例 💬推荐一款模拟面试、刷题神器👉 点击跳转进入网站 1、题目 题目:有一分数序列:2/1,3/2,5/3,8/5,13/8,21/13…求出这个数列的前 20 项之和。 分析…

Ionic Mac 环境配置

2019独角兽企业重金招聘Python工程师标准>>> Ionic Mac 环境配置 安装cordova之前要安装nodejs 会包含npm安装(npm是个包管理器),到官网下载https://nodejs.org/en/download/ 是个pkg包下载之后双击下载包运行然后 step …

(03).NET MAUI实战 基础控件

1.概要本章将继续介绍.NET MAUI中的常用基础控件,让刚刚接触MAUI的小伙伴有写基础的认识,心里有底开发起来将得心应手。下面将列出一些常用的基础控件:控件名中文名称说明Button按钮与WPF中的基础用法无太大变化CheckBox单选框与WPF中的基础用…

ffmpeg源码分析及mp4文件解析

一.mp4文件的组织 1. mp4文件的box(ffmpeg中叫atom) mp4是由一系列的box组成的,每个box的header是8个字节(4字节的长度,4字节的type) 第一个box比较特殊,其type类型为ftyp,还包含一个sub-type 0000000: 0000 0020 6674 7970 6973 6f6d 0000 0200 ... f…

C++库(Google Breakpad)

Google Breakpad是什么? 一个开源的多平台崩溃报告系统。 Google breakpad是一个非常实用的跨平台的崩溃转储和分析模块,它支持Windows,Linux和Mac和Solaris。由于他本身跨平台,所以很大程度上减少了我们在平台移植时的工作&#…

java eleven进度条

2019独角兽企业重金招聘Python工程师标准>>> 一个矩形组件 MethodDescribleJProgrssBar()不带进度字符,最小值0最大值100的水平进度条JProgressBar(int orient)VERTICAL/HORIZONTALJProgressBar(int in,int max)指定最大最小的水平进度条JProgressBar(in…

Docker:多阶段构建 ASP.NET Core 应用镜像

本文选自『.NET大牛之路』知识星球,发布于2022年05月25日。今天我们一起来写 Dockerfile 构建一个 ASP.NET Core 应用镜像,同时还会将镜像发布到 Docker Hub 仓库。1创建示例 Web 应用程序为了演示,我们先创建一个 ASP.NET Core 应用程序&…

[转]【JAVA各版本特性】JAVA 1.0

闲来想了解下各版本之间的特性,搜索没有最新的特性说明,故想写一份。废话不多说。 JDK Version 1.0 1996-01-23 Oak(橡树) 初代版本,伟大的一个里程碑,但是是纯解释运行,使用外挂JIT,性能比较差&#xff0…

北京Uber优步司机奖励政策(3月11日)

滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfryf/p/4612609.html 优步奖励低/不挣钱/怎么办?看这里:http://www.cnblogs.com/mfry…

【招聘(广州)】成功易(广州).Net Core中高级开发工程师

成功易(广州)信息技术有限公司简介成功易是一家集团性公司,创立于2002年,总部位于北京,旗下拥有7家子公司。广州成功易成立于2019年,人员逐渐增长150人,组织架构完善, 我们是腾讯广告…

xcode 设置快捷键 整行上下移动

2019独角兽企业重金招聘Python工程师标准>>> 设置整行代码上下移动:找到Xcode中的自带的配置文件:/Applications/Xcode.app/Contents/Frameworks/IDEKit.framework/Versions/A/Resources/IDETextKeyBindingSet.plist用文本编辑IDETextKeyBind…

用.Net Core接入微信公众号开发

Part1前言最近想写一点基于.Net Core微信公众号开发的文章Part2测试公众号申请测试公众号申请地址:https://mp.weixin.qq.com/debug/cgi-bin/sandbox?tsandbox/login微信公众号开发文档:https://developers.weixin.qq.com/doc/offiaccount/Getting_Started/Overview.html通过微…

腾讯、百度、小米等7家互联网各大厂的中台建设怎么样了?

中台是真正为前台而生的平台(可以是技术平台,业务能力甚至是组织机构),它存在的唯一目的就是更好的服务前台规模化创新,进而更好的响应服务引领用户,使企业真正做到自身能力与用户需求的持续对接。 以下转载…

JAVA基础知识之网络编程——-基于AIO的异步Socket通信

异步IO 下面摘子李刚的《疯狂JAVA讲义》 按照POSIX标准来划分IO,分为同步IO和异步IO。对于IO操作分为两步,1)程序发出IO请求。 2)完成实际的IO操作。 阻塞IO和非阻塞IO都是针对第一步来划分的,如果发出IO请求会阻塞线程…