首先我们先了解一下计算机网络的三大模型

经典的OSI七层模型:

物理层、数据链路层、网络层、传输层、会话层、表示层、应用层

简化的理论五层模型:

物理层、数据链路层、网络层、传输层、应用层(对应于七层模型的会话层、表示层、应用层)

实际应用中的TCP/IP体系四层模型:

网络访问层(五层模型的物理层和数据链路层的统一)、网络互连层、传输层、应用层

TCP协议位于三大模型中的传输层

传输层主要协议为UDP和TCP,其中 TCP 协议与 UDP 最大的不同就是 TCP 提供可靠的传输,而 UDP 提供的是不可靠传输。

为了提供可靠的传输,就引出了今天的第一个问题。

TCP的三次握手

首先我们来看一下两军问题:

假设一支蓝军指挥官向另外一支蓝军发出消息:“我建议在明天佛晓发起进攻,请确认。”如果消息到达了另一支蓝军,其指挥官同意这一建议,并且他的回信也安全的送到,那么能否进攻呢?
不能。这是一个两步握手协议,因为该指挥官无法知道他的回信是否安全送到了,所以,他不能发起进攻,改进协议,将两步握手协议改为三步握手协议,这样,最初提出建议的指挥官必须确认对该建议的应答信息。假如信息没有丢失,并收到确认消息,则他必须将收到的确认信息告诉对方,从而完成三步握手协议。
然而,这样他就无法知道消息是否被对方收到,因此,他不能发起进攻。那么现在采用四步握手协议会如何呢?结果仍是于事无补。

那为什么三次握手就可以建立起一个真正的可靠连接,而不是两次握手,或者四次握手呢?

这个问题的本质是, 信道不可靠, 但是通信双发需要就某个问题达成一致,而为了达到一致,双方需要经过多少次应答。

其实,正如两军问题说描述,无论多少次握手,都会有连接不上的不确定性。而三次握手,保证了信道的基本可靠性,是理论上的最小值

在谢希仁著的《计算机网络》中提及的三次握手的目的是

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

谢希仁版《计算机网络》中的例子是这样的:

“已失效的连接请求报文段”的产生在这样一种情况下:client发出的第一个连接请求报文段并没有丢失,而是在某个网络结点长时间的滞留了,以致延误到连接释放以后的某个时间才到达server。
本来这是一个早已失效的报文段。但server收到此失效的连接请求报文段后,就误认为是client再次发出的一个新的连接请求。于是就向client发出确认报文段,同意建立连接。
假设不采用“三次握手”,那么只要server发出确认,新的连接就建立了。由于现在client并没有发出建立连接的请求,因此不会理睬server的确认,也不会向server发送数据。但server却以为新的运输连接已经建立,并一直等待client发来数据。
这样,server的很多资源就白白浪费掉了。采用“三次握手”的办法可以防止上述现象发生。例如刚才那种情况,client不会向server的确认发出确认。server由于收不到确认,就知道client并没有要求建立连接。”

如果更深层次的解析为什么需要三次握手,那我们就得从三次握手发送的每一个包开始说起。

TCP报文格式简介:

(1)序号(sequence number):Seq序号,占32位,用来标识从TCP源端向目的端发送的字节流,发起方发送数据时对此进行标记。

(2)确认号(acknowledgement number):Ack序号,占32位,只有ACK标志位为1时,确认序号字段才有效,Ack=Seq+1。

(3)标志位(Flags):共6个,即URG、ACK、PSH、RST、SYN、FIN等。具体含义如下:

  • URG:紧急指针(urgent pointer)有效。
  • ACK:确认序号有效。
  • PSH:接收方应该尽快将这个报文交给应用层。
  • RST:重置连接。
  • SYN:发起一个新连接。
  • FIN:释放一个连接。

上面三个字段都在三次握手中起到了重要的作用。

详解三次握手过程
TCP连接(三次握手)的建立。这个连接必须是一方主动打开,另一方被动打开的。以下为客户端主动发起连接的图解:

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

第一次:

首先客户端向服务器端发送一段TCP报文,其中:

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

第二次:

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

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

第三次:

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

  • 标志位为ACK,表示“确认收到服务器端同意连接的信号”(即告诉服务器,我知道你收到我发的数据了);
  • 序号为Seq=x+1,表示收到服务器端的确认号Ack,并将其值作为自己的序号值;
  • 确认号为Ack=y+1,表示收到服务器端序号Seq,并将其值加1作为自己的确认号Ack的值;
  • 随后客户端进入ESTABLISHED阶段
    服务器收到来自客户端的“确认收到服务器数据”的TCP报文之后,明确了从服务器到客户端的数据传输是正常的。结束SYN-SENT阶段,进入ESTABLISHED阶段。
    —————————————————————————————————
    在客户端与服务器端传输的TCP报文中,双方的确认号Ack和序号Seq的值,都是在彼此Ack和Seq值的基础上进行计算的,这样做保证了TCP报文传输的连贯性。一旦出现某一方发出的TCP报文丢失,便无法继续"握手",以此确保了"三次握手"的顺利完成。

经过上面的简述,我相信你对为什么需要三次握手已经有了一个认识。

TCP的四次挥手

三次握手是用来建立TCP连接的,而四次挥手则是释放TCP连接的。

由于TCP是全双工通信的,所以关闭也需要双方的关闭。连接的释放必须是一方主动释放,另一方被动释放。


我们先来说一下四次挥手的步骤:

挥手之前主动释放连接的客户端结束ESTABLISHED阶段。随后开始“四次挥手”:

第一次:

首先客户端想要释放连接,向服务器端发送一段TCP报文,其中:

  • 标记位为FIN,表示“请求释放连接“;
  • 序号为Seq=U;
  • 随后客户端进入FIN-WAIT-1阶段,即半关闭阶段。并且停止在客户端到服务器端方向上发送数据,但是客户端仍然能接收从服务器端传输过来的数据。(这里不发送的是正常连接时传输的数据(非确认报文),而不是一切数据,所以客户端仍然能发送ACK确认报文。)

第二次:

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

  • 标记位为ACK,表示“接收到客户端发送的释放连接的请求”;
  • 序号为Seq=V;
  • 确认号为Ack=U+1,表示是在收到客户端报文的基础上,将其序号Seq值加1作为本段报文确认号Ack的值;
  • 随后服务器端开始准备释放服务器端到客户端方向上的连接。

客户端收到从服务器端发出的TCP报文之后,确认了服务器收到了客户端发出的释放连接请求,随后客户端结束FIN-WAIT-1阶段,进入FIN-WAIT-2阶段

前"两次挥手"既让服务器端知道了客户端想要释放连接,也让客户端知道了服务器端了解了自己想要释放连接的请求。于是,可以确认关闭客户端到服务器端方向上的连接了

第三次:

服务器端自从发出ACK确认报文之后,经过CLOSED-WAIT阶段,做好了释放服务器端到客户端方向上的连接准备,再次向客户端发出一段TCP报文,其中:

  • 标记位为FIN,ACK,表示“已经准备好释放连接了”。注意:这里的ACK并不是确认收到服务器端报文的确认报文。
  • 序号为Seq=W;
  • 确认号为Ack=U+1;表示是在收到客户端报文的基础上,将其序号Seq值加1作为本段报文确认号Ack的值。

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

第四次:

客户端收到从服务器端发出的TCP报文,确认了服务器端已做好释放连接的准备,结束FIN-WAIT-2阶段,进入TIME-WAIT阶段,并向服务器端发送一段报文,其中:

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

随后客户端开始在TIME-WAIT阶段等待2MSL。

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

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

在客户端与服务器端传输的TCP报文中,双方的确认号Ack和序号Seq的值,都是在彼此Ack和Seq值的基础上进行计算的,这样做保证了TCP报文传输的连贯性,一旦出现某一方发出的TCP报文丢失,便无法继续"挥手",以此确保了"四次挥手"的顺利完成。

抛出问题

为什么最后客户端在TIME-WAIT阶段要等2MSL?

为的是确认服务器端是否收到客户端发出的ACK确认报文

MSL指的是Maximum Segment Lifetime:一段TCP报文在传输过程中的最大生命周期。

当客户端发出最后的ACK确认报文时,并不能确定服务器端能够收到该段报文。所以客户端在发送完ACK确认报文之后,会设置一个时长为2MSL的计时器。

2MSL即是服务器端发出为FIN报文和客户端发出的ACK确认报文所能保持有效的最大时长。

服务器端在1MSL内没有收到客户端发出的ACK确认报文,就会再次向客户端发出FIN报文;

  • 如果客户端在2MSL内,再次收到了来自服务器端的FIN报文,说明服务器端由于各种原因没有接收到客户端发出的ACK确认报文。客户端再次向服务器端发出ACK确认报文,计时器重置,重新开始2MSL的计时;
  • 否则客户端在2MSL内没有再次收到来自服务器端的FIN报文,说明服务器端正常接收了ACK确认报文,客户端可以进入CLOSED阶段,完成“四次挥手”。

所以,客户端要经历时长为2MSL的TIME-WAIT阶段;这也是为什么客户端比服务器端晚进入CLOSED阶段的原因

为什么四次挥手不能把中间两次压缩成一次变成三次挥手?

不同于三次握手中,同一次握手里面有SYN建立连接报文与ACK确认接收报文。

四次挥手将FIN释放连接报文和ACK确认接收报文分开成第二次和第三次挥手传输的。

  • 这是因为第三次握手在被动方服务器端结束CLOSED阶段进入“握手”阶段并不需要任何准备,可以直接返回SYN和ACK报文,开始建立连接。

  • 而释放连接时,被动方服务器,突然收到主动方客户端释放连接的请求时并不能立即释放连接,因为还有必要的数据需要处理,所以服务器先返回ACK确认收到报文,经过CLOSE-WAIT阶段准备好释放连接之后,才能返回FIN释放连接报文。

如有错误敬请指出!

参考:
https://baijiahao.baidu.com/s?id=1654225744653405133&wfr=spider&for=pc
https://www.bilibili.com/video/BV1vT4y1w7GZ/?spm_id_from=333.788.recommend_more_video.1
https://blog.csdn.net/tennysonsky/article/details/45622395

面试小知识(2)为什么TCP需要三次握手和四次挥手相关推荐

  1. 面试官口中的:TCP的三次握手和四次挥手,你理解透了吗?

    三次握手建立链接,四次挥手断开链接.这个问题算非常经典的问题,也是面试官非常喜欢问的问题. 不夸张的说,校招面试的时候每一家公司都问到过关于三次握手和四次挥手相关的问题,相信大家也都差不多被面试官各种 ...

  2. 面试常问!!TCP的三次握手与四次挥手理解

    作者:青柚_ 原文:https://blog.csdn.net/qq_38950316/article/details/81087809 先来张图! 序列号seq:占4个字节,用来标记数据段的顺序,T ...

  3. 【运维面试】面试官问到tcp/ip三次握手,四次挥手,这么回答就对了

    我之前面试过很多运维人员,每次都绕不开tcp/ip三次握手,四次挥手: 面试者的回答也是八仙过海各显神通 有讲故事的,有画图的,有把自己讲晕了的: 那这个该怎么回答呢? 我总结下来可以这么来说: 三次 ...

  4. 了解TCP的三次握手和四次挥手

    了解TCP的三次握手和四次挥手 一.    TCP/IP OSI参考模型 了解TCP的三次握手和四次挥手,我们首先从TCP/IP OSI参考模型说起. OSI(Open System Intercon ...

  5. TCP的三次握手和四次挥手及常见面试题

    一.前言 今天上掘金查看热门文章,发现一篇好文 ★前端 100 问:能搞懂 80% 的请把简历给我 ★ ,此文包含100个前端面试问题,仔细阅读完所有题目后,顿感身中数刀无法呼吸,留下了没有技术的泪水 ...

  6. TCP和UDP区别以及TCP的三次握手和四次挥手

    TCP和UDP的概念 TCP: 传输控制协议(TCP,Transmission Control Protocol)是一种面向连接的.可靠的.基于字节流的传输层通信协议 UDP: Internet 协议 ...

  7. 【重难点】【计算机网络 02】TCP 和 UDP 的区别、TCP 的三次握手和四次挥手、HTTP 和 HTTPS、HTTP 各版本之间的区别、HTTP 如何实现长连接

    [重难点][计算机网络 02]TCP 和 UDP 的区别.TCP 的三次握手和四次挥手.HTTP 和 HTTPS.HTTP 各版本之间的区别.HTTP 如何实现长连接 文章目录 [重难点][计算机网络 ...

  8. TCP的 “三次握手” 和“四次挥手”,到底是什么鬼?

    轻松了解HTTP协议 为什么要学习网络协议呢?为什么要学习计算机网络呢?显然这很重要,至少能够帮助你找到工作的原因之一,学习网络知识点太多太多,没有那么快就能记住. 理解的网络协议,应该从背景原理去着 ...

  9. 通俗易懂理解TCP协议三次握手和四次挥手及其常见问题

    TCP协议三次握手和四次挥手 三次握手 如果建立连接只需要2次握手,可能会出现的情况 四次挥手 为什么建立连接是三次握手,关闭连接确是四次挥手呢? TIME_WAIT状态有什么作用,为什么主动关闭方没 ...

  10. 一文搞懂TCP的三次握手和四次挥手

    目录 1.三次握手 2.四次挥手 3.11种状态名词解析 TCP的三次握手和四次挥手实质就是TCP通信的连接和断开. 三次握手:为了对每次发送的数据量进行跟踪与协商,确保数据段的发送和接收同步,根据所 ...

最新文章

  1. 网络系统结构和设计的基本规则(Basic rules for network system architecture and design)
  2. 整理:各个浏览器及web服务器对URL(get)长度的限制
  3. 【Git】Git 分支管理 ( 解决分支合并冲突 | 创建并切换分支 git switch -c feature1 | 修改 feature1 分支并提交 | 修改 master 主版本并提交 )
  4. 学习强制删除正在运行的文件
  5. AE合成自动智能剪裁脚本:Auto Crop for Mac
  6. (33)FPGA原语设计(BUFGCE)
  7. asp.net ajax 1.0中detailview与updatepanel混合使用的例子
  8. GAMES101 Transformation Cont.
  9. illustrator插件-拼版功能开发-印前角线-js脚本开发-ai插件
  10. 打印参数量GFLOPs等的参考链接暂存+pycocotools安装
  11. Python生成自定义表头Excel
  12. 浅谈分形艺术是什么?
  13. 终止所有mysql进程_如何查找和终止MySQL进程
  14. 【Get深一度】矩形窗/bartlett/Blackman/hamming/Hanning/kaiser -相控阵雷达原理
  15. java 错误代码1603_java更新时出现错误代码1603的解决方法
  16. H5页面跳转到微信公众号首页
  17. 解决外接显示屏后CPU占用率过高问题
  18. 牙疼不是病疼起来真要命!教你几个止疼小偏方
  19. Python爬虫与信息提取(八)将新浪热搜排名导入数据库
  20. java mifare_java – NTAG212 Mifare Ultralight与身份验证

热门文章

  1. 墨魂服务器维修,2013年10月22日定期维护公告
  2. 乌尔维·阿西莫夫和 .art的不解情缘
  3. CCS8.0和XDS100V3仿真器连接目标板失败的解决办法
  4. php.ini配置文件中文详细解释
  5. Android中的四大天王
  6. 全球液晶面板市场格局或将改变,TCL将超越京东方成为老大
  7. The Pilots Brothers refrigerator's 题解
  8. 1688以图搜货接口,1688图片搜索接口,拍立淘接口,以图搜商品接口,图片上传搜索商品接口,按图搜索接口代码对接参数说明
  9. 北斗时钟服务器(NTP服务器)让高考时间更加精准
  10. Rancher 轮换证书 和 Rancher 自身证书过期处理