第二十九篇:图解TCP三次握手,一次说透,TCP系列四

⼀开始,客户端和服务端都处于 CLOSED 状态。先是服务端主动监听某个端⼝,处于 LISTEN 状态。

接下来这部分内容的介绍将影响你能不能彻底理解了TCP的三次握手。

一、划重点只有服务端启动了端口监听客户端TCP握手才能建立连接,那么服务端启动的时候都做了哪些工作呢?

1.服务端创建一个套接字(socket)(全局套接字fd)

2.服务端将套接字(socket)绑定在某个端口,然后开始监听

3.启动监听的时候,TCP的软件程序内核会在主机维护一个哈希表存放半连接,该半连接指三次握手客户端发来的SYN报文后服务端生成的初始信息

  4.同时TCP的软件程序内核也会生成一个用链表实现的队列存放全连接全连接指的是三次握手后客户端发来ACK报文后服务端生成的完整连接信息

全连接和半连接都会存放在内存里面,其在内存里的结构如图所示。

随后客户端发起连接握手情况如下

① 第一次握手:客户端发送连接请求

第 1 次握手建立连接时,客户端向服务器发送 SYN 报文(SEQ=X,SYN=1),并进入 SYN_SENT 状态,等待服务器确认,如图所示。

那客户端具体做了哪些事情呢

1)获取文件句柄对应的套接字(socket)对象

2)从用户空间复制要连接的远端IP地址和端口信息

3)设置 socket 状态为 TCP_SYN_SENT

4)动态选择一个端口

5)生成一个连接信息,该信息包含了,报文序列号、最大序列号等;并构造为一个 SYN 包;

客户端会随机初始化一个序号,假设为X,将此序号X置于 TCP ⾸部的「序列号」字段和连接信息的序列号字段中,表示包的序号是X,同时把 SYN 标志位置为 1 ,表示 SYN 报⽂。接着把第⼀个 SYN 报⽂发送给服务端,表示向服务端发起连接,该报⽂不包含应⽤层数据,之后客户端处于 SYN-SENT 状态。

客户端向服务端发送的SYN报文如下图所示。

6)设置TCP头部长度、初始化滑动窗口的大小

7)将第三步生成的连接信息添加到“发送队列”上

8)发送SYN报文

9)启动重传定时器,重传定时器的作用是当报文发送出去了之后,如果特定时间内没有收到确认报文就重发报文。

② 第二次握手:服务器响应 SYN

第 2 次握手实际上是做了两个工作,即 SYN+ACK(请求和确认)报文。

  • 服务器收到了客户端的请求,向客户端回复一个确认信息(ACK=x+1)。
  • 服务器再向客户端发送一个 SYN 包(SEQ=y)建立连接的请求,此时服务器进入 SYN_RECV 状态,如图所示。

此时服务器端做了哪些事情呢

1)服务端查看半连接队列是否满了,如果满了,并且tcp_syncookies 内核参数没有开启,直接丢弃;

2)查看全连接是不是满了,如果满了,且有 young_ack 的话,那么同样也是直接丢弃;

young_ack 是半连接队列里保持着的一个计数器。记录的是刚有SYN到达,没有被SYN_ACK重传定时器重传过SYN_ACK,同时也没有完成过三次握手的sock数量。

3)创建半连接内核对象

4)构造 syn+ack 报文

服务端收到客户端的 SYN 报⽂后,⾸先服务端也随机初始化一个序列号,将此序列号填⼊TCP ⾸部的「序列号」字段中;然后服务端把客户端传来的SYN报文中的X加1(SYN报文数据字段为空,这里默认当作传了一个字节的数据被服务端接收了),表示我收到了序列号为X的一个字节的报文, 然后把X+1 填⼊TCP ⾸部的「确认应答号」字段, 接着把 SYN和 ACK 标志位置为 1 。最后把该报⽂发给客户端,该报⽂也不包含应⽤层数据,之后服务端处于 SYNRCVD 状态。

客户端向服务端发送的ACK+SYN报文如下图所示。

5)发送 syn + ack 响应

6)半连接内核对象添加到半连接队列,并开启计时器

另外第二次握手其实是把两件事合并成了一件事,服务端接收到SYN请求,会给一个ACK应答报文,同时服务端还需要发送一个SYN请求报文,为了不浪费资源,合并在一个报文里面了,称为SYN+ACK报文。

③ 第三次握手:客户端响应 SYNACK

第 3 次握手,是客户端收到服务器的回复(SYN+ACK 报文)。此时,客户端也要向服务器发送确认包(ACK)。此包发送完毕客户端和服务器进入 ESTABLISHED 状态,完成 3 次握手,如图所示。

第三次握手客户端做了哪些事情呢

1)删除发送队列上的连接信息

2)删除SYN报文重发定时器

3)修改 套接字socket 状态为ESTABLISHED状态

4)初始化拥塞控制数据

5)打开连接保活计时器

6)申请和构造 ack 包

客户端收到服务端报⽂后,还要向服务端回应最后⼀个应答报⽂,⾸先设置该应答报⽂ TCP ⾸部 ACK 标志位置为 1 ,其次「确认应答号」字段填⼊ Y + 1 ,最后把报⽂发送给服务端,这次报⽂可以携带客户端到服务器的数据--即可以把请求数据发给服务端了,之后客户端处于 ESTABLISHED 状态。

服务器收到客户端的应答报⽂后,也进⼊ ESTABLISHED 状态。

注:从上⾯的过程可以发现第三次握⼿是可以携带数据的,前两次握⼿是不可以携带数据的

7)将ACK报文发送出去

服务端接收到信息做了什么呢?

  1. 从半连接队列里面获取半连接信息,创建子套接字socket;
  2. 将该半连接从半连接队列删除
  3. 将上面创建的子socket添加入全连接队列
  4. 将子socket的连接状态改成ESTABLISHED

至此,三次握手完成。

不管是全连接队列还是半连接队队列都有最大的长度限制,超过限制,TCP会直接丢弃或者返回RST下面的表格为linux系统的参数介绍

参数名称

说明

tcp_syncookies

当TCP半连接队列SYN队列满之后,开启tcp_syncookies,连接校验通过会直接进入到accept队列

tcp_abort_on_overflow

当TCP全连接队列满之后的策略,0:如果全连接队列满了,服务器端会丢掉客户单发送的ACK,1服务端会发送一个RST给客户端,表示废弃这次连接

TCP全连接队列大小设置

取值是 somaxconn 和backlog之间的最小值,cat /proc/sys/net/core/somaxconn,backlog在TCP程序中指定

tcp_syn_retries

当客户端发送SYN包之后等待服务端返回SYN_ACK,如果客户端很长时间没有收到SYN+ACK报文,会重发SYN包,重发的次数由该参数控制,cat /proc/sys/net/ipv4/tcp_syn_retries

tcp_fastopn

TCP Fastopen,可以减少三次握手的时延,当第一次握手成功后,后续再次握手客户端会携带有第一次握手中服务端返回的cookie,后续不用在进行三次握手,直接连接,0 关闭 1 作为客户端使用 Fast Open 功能 2 作为服务端使用 Fast Open 功能 3 无论作为客户端还是服务器,都可以使用 Fast Open 功能 。 cat /proc/sys/net/ipv4/tcp_fastopen

二、为何不能是两次握手

现在我们假设TCP是两次连接,那会出现以下问题:

① 相同两端可能生成多个连接,导致双方通信困惑,造成混乱

由于网络拥塞,客户端在特定时间内没有收到回复,会通过定时器重新发送一个SYN请求,但是第一个SYN请求并没有丢失,只是后到达,现在客户端和服务端都有两个连接信息,其实就是两个连接,那这会造成什么后果呢?

建立连接后,发送数据,不知道应该交给哪个连接去处理,因为两个以上的连接的信息都是相同的,相同的四元组,数据分片重组发现有分片丢失,这将是灾难的。

② 数据分片重组需要用到序列号,如果采用两次握手,第二次握手可能由于网络原因丢失,客户端没有收到服务端的序列号,此时,如果服务端发送数据给客户端,客户端将无法进行重组,因为它不知道从哪里开始进行重组。

③ 同时,因为可能会建立多个连接,也就是多个“连接信息”,但是其实只需要一个资源就可以了,所以两次连接可能会导致资源浪费。

总结:不能用两次握手的原因包括三点:

1.为了防⽌重复连接初始化,生成多个连接造成混乱

2.同步序列号数据的可靠性需要序列号来保证

3.避免生成多个连接造成资源浪费

三、为何三次握手能解决两次握手带来的问题

客户端连续发送多次 SYN 建立连接的报文,在网络拥堵情况下:

  • 一个「旧 SYN 报文」比「最新的 SYN 」 报文早到达了服务端;
  • 那么此时服务端就会回一个 SYN + ACK 报文给客户端;
  • 客户端收到后可以根据自身的上下文,判断这是一个历史连接(序列号过期),那么客户端就会发送 RST 报文给服务端,表示中止这一次连接。

可以看到,在三次握手的情况下, 可以在服务端建立连接之前,可以阻止掉了历史连接,从而保证建立的连接不是历史连接

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

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

相关文章

关于jmeter设置为中文问题之后无法保存设置的若干问题

1、jemeter如何设置中文模式 Options--->Choose Language--->Chinese(Simplifies), 如此设置后就可显示中文模式(缺点:下次打开还是英文);如下图所示: 操作完成之后: 但是下次重启之后依旧是英文; 2、在jmeter.…

TRIZ理论在医疗电子研发中的应用

TRIZ,全称“Theory of Inventive Problem Solving”(发明问题解决理论),是一种系统化、逻辑严谨的创新方法论。它通过对大量发明案例的深入分析和总结,提炼出一套行之有效的创新原理和解决方案,旨在帮助人们…

【Word原件测试资料合集】软件系统功能测试方案,软件测试方案(整体方案),软件测试文档-测试计划模版(功能与性能),软件测试流程

一、 前言 (一) 背景 (二) 目的 (三) 测试目标 (四) 适用范围与读者对象 (五) 术语与缩写 二、 软件测试实施流程 (一) 测试工作总体流…

Hive使用与介绍

Hive 是一个大数据处理工具,使用起来相对简单,主要是通过 HiveQL 查询语言与 Hive 数据库进行交互。以下是使用 Hive 的基本方法和步骤,包括如何安装 Hive、编写 HiveQL 查询,以及一些常用的操作示例。 1. Hive 安装与配置 Hive 依赖 Hadoop,必须先安装 Hadoop 并配置 H…

前端工程师面试题整理

前言 本文整理了一系列前端工程师面试中常见的 HTML、CSS 和 JavaScript 问题及其答案,涵盖基础知识、常见问题及面试技巧。适用于准备前端开发职位面试的候选人参考。 目录 前言HTML & CSS1. 对 WEB 标准以及 W3C 的理解与认识2. XHTML 和 HTML 有什么区别3.…

【java】thymeleaf模板怎么给JS赋值

【java】thymeleaf模板怎么给JS赋值 我们知道如果被标签绑定值是: <h3 th:text="${name}"></h3

026 elasticsearch文档管理(添加、修改、删除、批处理)-Java原生客户端

文章目录 1.添加文档2.更新文档3.删除文档4.根据id取文档对象5.批量操作bulk 1.添加文档 使用RestHightLevelClient对象 使用client对象的index方法添加文档 创建IndexRequest对象&#xff0c;其中包含了索引库名称、文档的id、文档的内容 {"id":"1",&qu…

MoH:融合混合专家机制的高效多头注意力模型及其在视觉语言任务中的应用

在深度学习领域,多头注意力机制一直是Transformer模型的核心组成部分,在自然语言处理和计算机视觉任务中取得了巨大成功。然而,研究表明并非所有的注意力头都具有同等重要性,许多注意力头可以在不影响模型精度的情况下被剪枝。基于这一洞察,这篇论文提出了一种名为混合头注意力…

GoFly快速开发框架集成ZincSearch全文搜索引擎-ZincSearch是ElasticSearch轻量级替代搜索引擎

前言 我们在项目开发中会遇到如下业务场景&#xff1a; 1. 电子商务&#xff1a;实现商品搜索与推荐、价格监控。 2. 日志分析&#xff1a;进行系统日志分析和网络流量监控。 3. 社交媒体&#xff1a;内容搜索与发现以及用户行为分析。 4. 企业知识管理&#xff1a;进行知识搜…

Excel:Cells(Rows.Count, 1).End(xlUp).Row和Cells(Rows.Count, 1).End(xlUp)有什么区别

Cells(Rows.Count, 1).End(xlUp).Row 和 Cells(Rows.Count, 1).End(xlUp) 是 VBA 中用于定位 Excel 工作表中单元格的两种不同用法。以下是它们的区别&#xff1a; 1. Cells(Rows.Count, 1).End(xlUp).Row 功能: 这个表达式返回的是一个行号&#xff08;Long 类型&#xff09…

聚类算法的代码解析与实现

谱聚类算法的代码解析与实现 本文将对一个基于未归一化拉普拉斯矩阵的谱聚类算法进行详细解析。该算法的实现源自 SpeechBrain 项目&#xff0c;适用于语音片段的聚类&#xff0c;例如语音分离、说话人识别等任务。我们将逐步分析代码的每个部分&#xff0c;并解释其背后的数学…

DS快速排序和归并排序的非递归实现(16)

文章目录 前言一、快排的非递归实现二、归排的非递归实现总结 前言 打破递归桎梏&#xff0c;迎接迭代解放&#xff01; 一、快排的非递归实现 我们要替代递归&#xff0c;就要用到迭代或者循环&#xff0c;也就是说&#xff0c;其核心思想是不变的&#xff0c;只是换一种方式来…

使用 CDN 后 Apache 的日志记录客户真实 IP

经常搭建网站服务器的都知道&#xff0c;在给站点使用了 CDN 后 Web 应用的日志记录里就会只记录 CDN 节点 IP 了&#xff0c;这就没法看到真实客户请求 IP&#xff0c;对于日志分析、运维日常维护来说就有点儿麻烦了&#xff0c;今天明月结合在五洛云服务器上搭建的Apache环境…

ElementPlus-Table表格-单选--TypeScript进阶篇

今天看个例子&#xff0c;这个例子是ElementPlus的组件Table表格下面的单选 <template> <el-table ref"singleTableRef" :data"tableData" highlight-current-row style"width: 100%" current-change"hand…

探索C嘎嘎:模版初阶

前言&#xff1a; 小编在前文讲述了C的内存管理&#xff0c;下面我们来开始继续探索C&#xff0c;开启C又一个重要的内容&#xff0c;模版初阶的详解&#xff0c;代码时间到&#xff01; 目录 1.泛型编程 1.1.引子 1.2.泛型编程 2.函数模版 2.1.函数模版的概念 2.2.函数模版的格…

基于知识图谱的电子元器件问答系统

你还在为寻找电子元器件的相关信息头疼吗&#xff1f;作为一名程序员或电子工程师&#xff0c;在项目中经常需要快速查询电子元件的属性或关联关系。今天给大家介绍一个可以大大提升工作效率的神器——基于知识图谱的电子元器件问答系统。这不仅是你学习和工作的好帮手&#xf…

解读华为云Kuasar多沙箱容器技术,带来更强隔离性和安全性

摘要&#xff1a;沙箱技术的引入&#xff0c;为容器提供了更强的隔离性和安全性&#xff0c;成为云原生技术的重要组成部分。 本文来源 《华为云DTSE》第五期开源专刊&#xff0c;作者&#xff1a;华为云云原生开源团队研发工程师。 近年来&#xff0c;云原生容器技术飞速发展&…

1.5 ROS架构

到目前为止&#xff0c;我们已经安装了ROS&#xff0c;运行了ROS中内置的小乌龟案例&#xff0c;并且也编写了ROS小程序&#xff0c;对ROS也有了一个大概的认知&#xff0c;当然这个认知可能还是比较模糊并不清晰的&#xff0c;接下来&#xff0c;我们要从宏观上来介绍一下ROS的…

详解Java之异常

目录 防御式编程 捕获异常 基础语法 示例1 【不处理异常】 示例2 【使用try catch捕获异常】 示例3 【catch只能处理对应的异常】 示例4 【catch可以有多个】 示例5 【可以用一个catch捕获所有异常】 示例6 【finally一定会执行】 示例7 【使用try回收资源】 示例8 …

【iOS】YYModel

目录 什么是YYModel &#xff1f; 如何使用YYModel &#xff1f; 最简单的Model 与网络请求结合 属性为容器类的Model 白名单和黑名单 Model的嵌套 结语 什么是YYModel &#xff1f; YYModel是一个用于 iOS 和 macOS 开发的高性能的模型框架&#xff0c;主要用于对象和…