百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 热门文章 > 正文

TCP协议的三次握手(建立连接)和四次挥手(关闭连接)

bigegpt 2024-08-28 12:26 5 浏览

web运维中,特别是在web调优中,对TCP连接的各种状态必须要有深入的了解,说到TCP的连接状态,主要是指的TCP协议的三次握手(即为建立连接)和四次挥手(即为关闭连接)过程中的各种连接状态。例如我们经常见到的ESTABLISHED、TIME_WAIT、SYN_SEND、SYN_RECV等状态,这就是TCP建立连接和关闭连接过程中的状态标识。

1、TCP三次握手的过程与状态

下图展示了TCP三次握手建立连接的状态图:

从图中可以看出三次握手的过程:

第一次握手:
客户端首先发送(SYN=1,seq=J)的同步报文给服务器端,然后客户端进入SYN_SEND状态,等待服务器发回确认报文;这就是第一次握手。
第二次握手:
服务器收到客户端的SYN报文后,如果同意客户端连接,则发送SYN-ACK(ACK=1,ack=J+1,SYN=1,seq=K)报文给客户端,然后服务端进入SYN_RECV状态,等待客户端发回确认报文;这就是第二次握手过程。
第三次握手:
客户端收到服务器的SYN-ACK报文后,还需要向服务器再给出确认,此时,客户端会再次发送一个ACK(ACK=1,ack=K+1)确认报文给服务器,然后客户端进入ESTABLISHED状态;再服务器端收到客户端的确认报文后,也会进入ESTABLISHED状态;此时,TCP连接就此建立成功。接着客户端就可以发送数据了。

这就是TCP的三次握手过程,看似很简单,但是要深刻理解,却不容易,针对上面的三次握手过程,我们也可以通过大白话进行一遍重述,以便大家理解更深刻。用大白话讲就是:

第一次握手:客户端对服务器说:“hello,你能听到我说的话吗?”
第二次握手:服务器回答客户端说:“嗯,我能听到,那你能听到我说的话吗?”
第三次握手:客户端回答服务器说:“嗯,我也能听到了!”

这样,三次握手完毕后,客户端会继续对服务器说:“好,你现在听我说”, 然后客户端就开始一直说话了(其实就是HTTP请求)。

其实,在TCP第三次握手后,客户端就可以对服务器发起 HTTP 请求了。看到这里,可能有同学要发问了,为啥是三次握手,我看两次就行了,非也,三次握手是有依据的,三次握手是为了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误。

举个例子,假如仅仅是二次握手成立,那么会存在下面这个情况:

客户端对服务器发起请求,这个请求没有丢失,它在某个网络路由节点处滞留了,过了很久后,服务器才收到这个其实已经失效了的请求,但是服务器不知道这个请求已经失效了,还是向客户端发送确认建立连接的信息,于是连接建立完成。但是客户端现在并不需要发送请求,于是客户端就不会理睬服务器已经建立起来的连接,也不会向服务器发送任何请求数据。就这样,服务器一直在等待,等待着客户端发送请求数据过来,然而客户端现在压根就不想理会服务器,这样就导致服务器浪费了很多的资源。

但是,如果是三次握手的情况下,就不会存在这种情况了,继续来分析:
紧接着上面的例子,在服务器发出连接确认的信息后,如果服务器没有收到客户端的确认信息(也就是第三次握手),就不会建立连接了,这样,服务器就不会出现傻傻的等待状态了,而这种等待会大量浪费资源。

2、SYN攻 击与半连接队列

通过上面分析,我们知道了三次握手的必要性,需要确认两次才会建立连接。其实,在服务器收到客户端SYN报文后,会维护一个半连接队列,该队列为每个客户端的SYN包(syn=j)开设一个条目,此条目表明服务器已收到SYN报文,并向客户端发出确认,正在等待客户端的ACK报文。

如果服务器等待一段时间后没有收到客户端的ACK报文,那么服务器会重新发送SYN-ACK报文给客户端,然后继续等待着;如果服务器等待一段时候后仍然没收到客户端的ACK 报文,服务器会进行第二次重传SYN-ACK报文给客户端,如此循环,直到达到服务器设置的最大重传次数之后,服务器才会将连接信息从半连接队列中删除掉。

这样的连接信息也叫做“半连接请求”。

SYN攻 击,这个大家可能都听说过,它就是利用TCP协议的漏洞,通过发送大量半连接请求,耗费服务器CPU和内存资源。通常情况下,SYN攻 击者会在短时间内大量伪造不存在的IP地址,然后向服务器发送大量SYN包,而服务器就需要回复确认包,并等待客户端回复。但是客户端源地址是伪造不存在的,因而不可能回复服务器,而服务器需要不停重发确认包直至超时,这些伪造的SYN包会长时间占用未连接队列,导致正常的SYN请求被丢弃,最终的结果表现为:目标系统运行缓慢,严重者引起网络堵塞甚至系统瘫痪。

这就是SYN攻 击的原理。那么如何解决这个问题呢,后面会介绍到。

3、四次挥手(关闭连接)的过程

连接建立后,数据传输完毕,就会进入关闭连接节点,在关闭连接过程中,需要完成四次挥手,因为不管是客户端还是服务端,都可以发起挥手动作,所以下面我们以主机A和主机B区分。四次挥手(关闭连接)的过程如下图所示:

从图中可以看出四次挥手的过程:

第一次挥手:
主机A向主机B发送(FIN=1,seq=M)FIN报文,请求关闭连接,然后进入FIN_WAIT_1状态;
第二次挥手
主机B收到FIN报文并确认后,向主机A发送(ACK=1,ack=M+1)ACK报文,表示同意主机A,这时,主机B进入CLOSE_WAIT状态;主机A收到ACK报文后,马上进入FIN_WAIT_2状态;
第三次挥手
主机B也可以给A发送(FIN=1,seq=N)FIN报文,请求关闭连接,然后主机B进入LAST_ACK状态;
第四次挥手
主机A收到FIN报文确认后,向主机B发送(ACK=1,ack=N+1)ACK报文,表示同意主机B,然后主机A进入TIME_WAIT状态,经过2MSL之后,A自动进入CLOSED状态,四次挥手结束。当主机B收到A的ACK报文后,马上就进入CLOSED状态。

说明:MSL:Maxinum Segment Lifetime(最长报文段寿命),根据RFC793建议该值为2分钟。

这就是完整的四次挥手的过程,比三次握手稍微复杂些。下面再通过大白话解析下四次挥手的过程

第一次挥手:主机A对主机B说:“hello,朋友!我这边没有数据要给你了,我们关闭连接吧”
第二次挥手:主机B回答主机A说:“嗯,明白,我现在也不需要你的数据了;不过我要先看看我这边还有没有数据要发送给你”,主机A回答主机B说:“收到”
第三次挥手:主机B又对主机A说:“嗯,我这边也没有数据要传给你了,我们关闭连接吧”
第四次挥手:主机A回答主机B说:“好的!我同意!”。主机B听到主机A的回答后,二话没说,直接就把连接给关闭了。
主机A没有听到主机B的回话,多少有点不放心,于是它等了一段时间后(4 分钟),才把连接彻底关闭。

这里面又会出现一个疑惑,为什么关闭连接要四次挥手呢,而不是三次,原因如下;

由于TCP连接是全双工的,也就是可以同时发送和接收,因此在关闭连接的时候,需要关闭发送和接收两个接口才能完全关闭连接。因而,在挥手的时候,发出FIN的主机A只是表示没有数据发送了,但是它还可以接收数据,说不定它还要接收B的数据呢,所以不能马上关闭连接,要等到收到主机B的FIN确认也没有数据传出去的时候,才能关闭连接。通俗一点来讲,就是:

主机B确认自己已经不需要主机A的数据后,发送ACK报文给主机A,告诉主机A,我不再接收你的数据了,你可以关闭发送接口了。这是第二次挥手。
然后再确认自己所有的东西都已发送完毕,又发送FIN报文给主机A,告诉主机A,我也没有东西要发送给你了,你可以关闭接收接口了。这是第三次挥手。

综上所述,挥手需要四次。

至于为什么主机A第四次挥手的时候,需要经过2MSL后才关闭接口呢,这是因为网络的不可靠性,主机A第四次挥手发送的ACK报文无法保证主机B一定能收到,有可能丢失,

所以主机A发送ACK报文后,进入TIME_WAIT的状态,这个状态的作用就是用来重发可能丢失的ACK报文。

好啦,至此,四次挥手彻底剖析完毕。

相关推荐

得物可观测平台架构升级:基于GreptimeDB的全新监控体系实践

一、摘要在前端可观测分析场景中,需要实时观测并处理多地、多环境的运行情况,以保障Web应用和移动端的可用性与性能。传统方案往往依赖代理Agent→消息队列→流计算引擎→OLAP存储...

warm-flow新春版:网关直连和流程图重构

本期主要解决了网关直连和流程图重构,可以自此之后可支持各种复杂的网关混合、多网关直连使用。-新增Ruoyi-Vue-Plus优秀开源集成案例更新日志[feat]导入、导出和保存等新增json格式支持...

扣子空间体验报告

在数字化时代,智能工具的应用正不断拓展到我们工作和生活的各个角落。从任务规划到项目执行,再到任务管理,作者深入探讨了这款工具在不同场景下的表现和潜力。通过具体的应用实例,文章展示了扣子空间如何帮助用户...

spider-flow:开源的可视化方式定义爬虫方案

spider-flow简介spider-flow是一个爬虫平台,以可视化推拽方式定义爬取流程,无需代码即可实现一个爬虫服务。spider-flow特性支持css选择器、正则提取支持JSON/XML格式...

solon-flow 你好世界!

solon-flow是一个基础级的流处理引擎(可用于业务规则、决策处理、计算编排、流程审批等......)。提供有“开放式”驱动定制支持,像jdbc有mysql或pgsql等驱动,可...

新一代开源爬虫平台:SpiderFlow

SpiderFlow:新一代爬虫平台,以图形化方式定义爬虫流程,不写代码即可完成爬虫。-精选真开源,释放新价值。概览Spider-Flow是一个开源的、面向所有用户的Web端爬虫构建平台,它使用Ja...

通过 SQL 训练机器学习模型的引擎

关注薪资待遇的同学应该知道,机器学习相关的岗位工资普遍偏高啊。同时随着各种通用机器学习框架的出现,机器学习的门槛也在逐渐降低,训练一个简单的机器学习模型变得不那么难。但是不得不承认对于一些数据相关的工...

鼠须管输入法rime for Mac

鼠须管输入法forMac是一款十分新颖的跨平台输入法软件,全名是中州韵输入法引擎,鼠须管输入法mac版不仅仅是一个输入法,而是一个输入法算法框架。Rime的基础架构十分精良,一套算法支持了拼音、...

Go语言 1.20 版本正式发布:新版详细介绍

Go1.20简介最新的Go版本1.20在Go1.19发布六个月后发布。它的大部分更改都在工具链、运行时和库的实现中。一如既往,该版本保持了Go1的兼容性承诺。我们期望几乎所...

iOS 10平台SpriteKit新特性之Tile Maps(上)

简介苹果公司在WWDC2016大会上向人们展示了一大批新的好东西。其中之一就是SpriteKitTileEditor。这款工具易于上手,而且看起来速度特别快。在本教程中,你将了解关于TileE...

程序员简历例句—范例Java、Python、C++模板

个人简介通用简介:有良好的代码风格,通过添加注释提高代码可读性,注重代码质量,研读过XXX,XXX等多个开源项目源码从而学习增强代码的健壮性与扩展性。具备良好的代码编程习惯及文档编写能力,参与多个高...

Telerik UI for iOS Q3 2015正式发布

近日,TelerikUIforiOS正式发布了Q32015。新版本新增对XCode7、Swift2.0和iOS9的支持,同时还新增了对数轴、不连续的日期时间轴等;改进TKDataPoin...

ios使用ijkplayer+nginx进行视频直播

上两节,我们讲到使用nginx和ngixn的rtmp模块搭建直播的服务器,接着我们讲解了在Android使用ijkplayer来作为我们的视频直播播放器,整个过程中,需要注意的就是ijlplayer编...

IOS技术分享|iOS快速生成开发文档(一)

前言对于开发人员而言,文档的作用不言而喻。文档不仅可以提高软件开发效率,还能便于以后的软件开发、使用和维护。本文主要讲述Objective-C快速生成开发文档工具appledoc。简介apple...

macOS下配置VS Code C++开发环境

本文介绍在苹果macOS操作系统下,配置VisualStudioCode的C/C++开发环境的过程,本环境使用Clang/LLVM编译器和调试器。一、前置条件本文默认前置条件是,您的开发设备已...