第二十九篇:图解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原件测试资料合集】软件系统功能测试方案,软件测试方案(整体方案),软件测试文档-测试计划模版(功能与性能),软件测试流程

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

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

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

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

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

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

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

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

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

探索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;云原生容器技术飞速发展&…

详解Java之异常

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

鸿蒙网络编程系列24-Web组件与应用互操作示例

1. APP内嵌网页与应用互操作概述 在通常的APP开发中&#xff0c;经常会采用内嵌网页的形式&#xff0c;通过网页来展现丰富的动态内容&#xff0c;虽少了很多原生开发的功能&#xff0c;但是这么做无可厚非&#xff0c;毕竟APP需要适配的系统平台很多&#xff0c;比如安卓、苹…

【HarmonyOS NEXT】权限申请及应用设置页跳转

关键词&#xff1a;鸿蒙、程序访问控制、定位、应用详情页、startability、want 在app开发过程中&#xff0c;常进行系统权限的申请以提供设备访问或个性化功能&#xff08;如扫一扫、城市定位、剪贴板等&#xff09;&#xff0c;从而保障应用功能的完整性&#xff0c;那么本期…

Jupyter notebook和Conda使用

Jupyter notebook和Conda使用 文章目录 Jupyter notebook和Conda使用AnacondaJupyter notebook简介页面使用技巧编写格式自动补全查看函数文档魔术命令远程访问交互式 Anaconda Anaconda是一个开源的Python发行版本&#xff0c;其包含了conda、Python等180多个科学包及其依赖项…

stm32实现esp8266连接到TCP服务器(二)未完

1.2 连接到TCP Server 1.2.1 使用网络助手&#xff0c;设立TCP服务器 ​ 编辑 1.2.2 连接服务器 ATCIPSTART"TCP","192.168.1.18",8080 //指令&#xff0c;注意双引号逗号都要半角(英文)输入 CONNECT //结果&#xff1a;成功 OK //结果&#xff1a;成功 …

jmeter中用csv data set config做参数化2

在jmeter中&#xff0c;使用csv data set config进行参数化是很重要的一个功能&#xff0c;但是这个功能的使用需要十分仔细和小心&#xff0c;因为细节之处往往决定着结果的正确与否。 举例&#xff1a; 一个登录接口用加密密码登录&#xff0c;一个登录接口用原始密码登录。…

STM32G4系列MCU的低功耗模式介绍

目录 概述 1 认识低功耗模式 1.1 低功耗模式的应用 1.2 低功耗模式介绍 2 低功耗模式的状态关系 2.1 低功耗模式可能的转换状态图 2.2 低功耗模式总结 3 运行模式 3.1 减慢系统时钟 3.2 外围时钟门控 3.3 低功耗运行模式&#xff08;LP运行&#xff09; 概述 本文主…

JavaFx学习--chapter02(网络对话)

chapter02(网络对话) 简单网络对话程序 设计任务&#xff1a;客户端向服务器发送字符串&#xff0c;并能读取服务器返回的字符串。 知识点&#xff1a;TCP套接字技术&#xff0c;C/S软件架构程序设计 重点理解&#xff1a;Java客户套接字类Socket和服务器套接字类ServerSoc…

蜜罐技术的出现究竟影响了什么

自网络诞生以来&#xff0c;攻击威胁事件层出不穷&#xff0c;网络攻防对抗已成为信息时代背景下的无硝烟战争。然而&#xff0c;传统的网络防御技术如防火墙、入侵检测技术等都是一种敌暗我明的被动防御&#xff0c;难以有效应对攻击者随时随地发起的无处不在的攻击和威胁。蜜…

linux线程 | 同步与互斥 | 互斥(下)

前言&#xff1a;本篇文章主要讲述linux线程的互斥的知识。 讲解流程为先讲解锁的工作原理&#xff0c; 再自己封装一下锁并且使用一下。 做完这些就要输出一堆理论性的东西&#xff0c; 但博主会总结两条结论&#xff01;&#xff01;最后就是讲一下死锁。 那么&#xff0c; 废…