详细剖析传输层协议(TCP和UDP)

详细讲解传输层的网络协议,为什么TCP是可靠连接协议,凭什么能做到不丢包,有哪些机制保证可靠呢?

TCP/UDP

  • UDP
  • TCP
    • **三次握手和四次挥手**
    • **滑动窗口**
    • **拥塞控制**
    • (socket套接字)**listen的第二个参数**

UDP

UDP也是传输层协议,当我们在应用层把数据序列化之后,并不是直接通过网络就能发送到对方主机,需要向下交付,交给传输层然后经过传输层协议进行封装报头,再向下交付。

这就是udp的整体数据,前八个字节就是udp的报头,是定长的,会拿结构体表示。后面的数据就是应用层数据。

在这里插入图片描述
如果收到的udp报文不完整,校验和会检查出来

TCP

下面是TCP的数据报头格式

在这里插入图片描述

  • 源端口号是我们发送方进程的端口
  • 目的端口号是接收方进程的端口
  • 32位序列号和确认序列号: tcp是面向字节流的,当应用层把数据拷贝到传输层的发送缓冲区内时,缓冲区可以使一个char类型的数组存储,例如发送1000个字节,确认序列号可以是0或者任意,如果是0开始,0+1000字节,服务端返回的报头中确认序列号就是1001,代表可以从1001个字节开始发送确认序号不但是对当前报文做确认,还是对之前所有报文做确认,代表前面所有报文都已经收到。
  • urg代表紧急指针是否有效,如果有效,16位紧急指针代表在有效载荷的偏移量,紧急数据只有一个字节,标志位就是表示不同类型的报文。

三次握手和四次挥手

下面是三次握手图解
在这里插入图片描述

tcp是一个可靠的传输协议,在服务端和客户端进行通信的时候,需要进行连接,被称为三次握手。

一台主机可能建立多个链接,所以OS需要把链接管理起来,采用struct结构体的方式,先描述,再组织,struct可能是位段

三次握手是由操作系统自动完成的。

为什么是3次握手?

  1. 没有明显的设计漏洞,一旦建立连接出现异常,可以嫁接给client,server成本较低
  2. 验证双方通信信道的通畅情况,三次握手是验证全双工通信信道通畅的最小成本。更多奇数次会有更高成本。
  3. 如果是两次,容易收到攻击,SYN洪水。三次是奇数次,客户端一定是最后一个发送ACK的。

下面是四次挥手图解
在这里插入图片描述

​ 四次挥手是由客户端向服务端发起FIN请求,然后服务端维持CLOSE_WAIT状态,然后ack回复。等到服务端把该发的数据全部发送给客户端之后,然后发送FIN请求,客户端收到这个请求维持TIME_WAIT状态一段时间,服务端维持LAST_ACK状态,等收到客户端回复的ACK,服务端关闭。

如果服务端收到来自客户端的第一次FIN请求,维持CLOSE_WAIT状态,如果不close(fd),服务端会一直维持CLOSE_WAIT状态。

客户端和服务端是平等的,上面的状态 是客户端请求服务端,如果是服务端先发送请求,也是一样的。

所以就解释了为什么云服务器上写代码时,如果服务端先断开连接,那么端口号就不能用了,因为最后一次发送ACK会进入TIME_WAIT状态,端口号还在被占用,会等待一段时间之后才会关闭连接。

//端口号复用,如果不想让server端进行time_wait的等待状态,可以调用下面接口。
int opt=1;
setsockopt(_sock,SOL_SOCKET,SO_REUSEADDR|SO_REUSEPORT,&opt,sizeof(opt));

滑动窗口

双方使用TCP协议,有发送缓冲区和接受缓冲区,每次发送的报文都要收到对应的ACK应答,应答报文里面有16位窗口大小,这个16位窗口大小代表了对方接收缓冲区的大小,防止报文发送过快引起报文丢失造成资源浪费,或者报文发送过慢引起效率底下的问题。

发送方和接收方有两种发送和接受的模式,一种是串行,就是发送一个报文等收到应答报文之后,才能发送下一个报文,这种效率低下。还有一种就是可以先发送多条报文给对方,然后对方对这些报文一一发送应答报文,这种是并行。
在这里插入图片描述

而在发送缓冲区里面有一个滑动窗口,滑动窗口里面的数据是可以不收到前面报文的应答报文,然后直接发送给对端的数据,例如像下面这样
在这里插入图片描述

那么这个窗口大小是多少呢?答案是一定不能超过对方接收缓冲区的大小。
在这里插入图片描述

TCP是面向字节流的,所以发送缓冲区也是以字节为单位的。winstart就是起始下标,winend就是结束下标,start 和end同时++,就是窗口在滑动。

补充知识:

  1. 滑动窗口只能向右滑,不能向左

  2. 滑动窗口根据对方接受能力可以变大变小,start不动end++就变大。end不动start++就变小。

  3. 每次的ACK报头中响应的确认序号就是下一次要发送的起始下标,起始下标加上窗口大小就是滑动窗口大小。

  4. 滑动窗口不会越界,因为可以把缓冲区设置成环形队列。

  5. 如果第一个报文或者中间报文丢失分为两种情况:

    1. ACK丢失,这个不必担心,因为后面报文的ACK如果收到了,就代表前面的一定收到了,确认序号就代表前面报文全部收到,下一次发送请从最大的确认序号开始发送。
    2. 数据丢失了,第一个数据或者中间的丢失了都是同理,如果第一个数据是1001-2000,第二个是2001-3000,以此类推,后面的数据返回的ACK报文的确认序号一定是1001,因为尽管2000后面的收到了,也不能不管1001~2000,后面多个ACK报文都是1001的确认序号,操作系统就知道报文丢失了,就会进行补发1001-2000这段数据。

拥塞控制

学习了上面的滑动窗口,我们明白了两端主机在进行通行时,已经把双方主机的情况考虑的特别全面了,例如确认应答,超时重传,三次握手四次挥手,还有基于流量控制的滑动窗口。但是我们的报文是在网络中进行传输的,网络中可是不止我们两台主机在通信,而是成千上万乃至上亿的主机在通信,所以网络中一定是同时存在大量的数据的,如果传输过程中因为网络的原因发生大量的丢包,这个怎么办呢?为什么呢?

如果是因为网络的原因丢包可能是因为网络中的数据太多发送拥塞,如果真的是因为发送了拥塞而丢包导致的,那么我们的通信双方第一时间可能会启动超时重传,但是网络中因为发生了堵塞的情况,这个时候网络中的多台主机同时启动超时重传机制,网络中本来就已经有大量的数据了,这样只会导致拥塞情况更加严重,所以这时候绝对不能再发送大量的数据了。

当发送大量的丢包时,OS就判断可能是网络中出现了拥塞,所以就需要对网络中的情况进行探测,试探的发送一个报文,如果没有回应,就说明网络拥塞严重,等待一段时间再探测。如果收到了ACK回应,就发送两个报文,如果再收到回应就发送四个报文。就这样以2的指数级别进行增长。以指数级别增长开始慢,后来就会特别快,当然也不会一直以指数级别增长下去,到达一定的阈值之后就会以线性的方式增长,这种机制叫做慢启动,用来摸清网络的承受能力。

OS需要一直来试探网络中数据的承受能力,来监听网络的状态,所有就有了拥塞窗口,来进行拥塞控制。

所以上面的滑动窗口的大小其实是不但要考虑接收方缓冲区的大小,还要考虑拥塞窗口的大小,如果拥塞窗口比接受缓冲区数据承载能力大,就不必考虑拥塞窗口,反之就要以拥塞窗口的大小为滑动窗口的大小。

(socket套接字)listen的第二个参数

之前学习listen函数有两个参数,第一个就是socket返回的文件描述符,但是第二个参数就没有讲解,我们现在理解一下第二个参数的含义。

使用TCP协议,先创建socket套接字之后,然后listen函数监听和server端连接的所有客户端,收到和server连接的客户端的请求,OS在底层会自动完成三次握手,然后进入ESTABLISHED状态。
在这里插入图片描述

然后用accept函数和客户端进行通信,在accept被调用之前,客户端和服务端就已经建立好连接了,accept只不过是把已经建立好的连接拿到上层,之前我们把第二个参数设置成了32或者更大,就是按照上面的流程完成了连接通信,如果我们把第二个参数设置成1,会发生什么?

如果设置成1,并且不调用accept,不让上层把建立好的连接取走,那么前两个客户端的连接是正常的,客户端和服务端都会进入ESTABLISHED状态,到了第三个就会出现问题,第三个客户端也会维持ESTABLISHED状态,但是服务端是SYN_RCVD状态,也就代表服务端给客户端响应SYN+ACK之后并没有进入ESTABLISHED状态。

这是因为OS底层会保持两个队列,一个全连接队列,一个半连接队列,全连接队列的最大个数就是第二个参数加一,只要全连接队列中没有连接被accept取走,之后来的所有连接请求只能保持在半连接队列里面,并且这个半连接队列的生命周期很短。

这样并不是服务器只能同时和两个连接的客户端通信,而是没有被accept来得及读取到的连接就先放在全连接队列里面,一旦accept读取到了这个全连接,这个全连接就会被上层读走,就会被移除。然后半连接队列就能向全连接队列push一个连接。

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

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

相关文章

数据可视化:艺术与科学的交汇点,如何让数据“开口说话”?

数据可视化:艺术与科学的交汇点,如何让数据“开口说话”? 数据可视化,是科技与艺术的结合,是让冰冷的数字变得生动有趣的桥梁。它既是科学——讲究准确性、逻辑性、数据处理的严谨性;又是艺术——强调美感…

解决使用lettuce连接Redis超时的问题(tcpUserTimeout 参数失效问题)

问题背景 lettuce 连接Redis的主从实例,当主节的主机异常下电重启后,由于没有发送RST 包,导致 lettuce 一直在复用之前的TCP链接,然后会出现连接超时的情况。一直出现io.lettuce.core.RedisCommandTimeoutException: Command tim…

如何使用python保存字典

在Python中,可以通过多种方式将字典(dict)保存到文件中,并能够随时读取恢复。以下是几种常见的方法: 1. 使用 json 模块(推荐) 适用场景:需要人类可读的文件格式,且数据不…

SQL 与 Python:日期维度表创建的不同选择

文章目录 一、日期维度表概述日期维度表结构 二、使用 SQL 创建日期维度表2.1 表结构设计2.2 数据插入2.3 SQL 创建方式的优势与局限 三、使用 Python 创建日期维度表3.1 依赖库引入3.2 代码实现3.3 Python 创建方式的优势与局限 四、应用场景与选择建议4.1 应用场景4.2 选择建…

如何用postman进行批量操作

业务场景: 有些时候,我们会需要批量的将SAP B1系统中的几千条的数据删除或者取消单据,这个时候,一条条去操作,指定是到猴年马月了。SAP Business One本身提供了DTW这个工具,但是这个更新,可以操…

Mysql如何完成数据的增删改查(详解从0到1)

前言: Mysql可能是每个程序员的必修课,可以说是使用起来是没有什么问题的,但是作为一名合格的程序猿,深入学习Mysql的内部工作原理是非常有必要的,主要是理解和学习Mysql的底层思想,希望在日后如遇到一些&…

单片机嵌入式按键库

kw_btn库说明 本库主要满足嵌入式按键需求,集成了常用的按键响应事件:高电平、低电平、上升沿、下降沿、单击、双击、长按键事件。可以裸机运行,也可以配合实时操作系统运行。 本库开源连接地址:连接 实现思路 本库采用C语言进行…

Qt—鼠标移动事件的趣味小程序:会移动的按钮

1.项目目标 本次根据Qt的鼠标移动事件实现一个趣味小程序:当鼠标移动到按钮时,按钮就会随机出现在置,以至于根本点击不到按钮。​​​​​ 2.项目步骤 首先现在ui界面设计控件(也可以用代码的方式创建,就不多说了) 第一个按钮不需…

MySQL的information_schema在SQL注入中的关键作用与防御策略

目录 一、information_schema的核心价值 二、攻击利用场景与示例 1. 联合查询注入(Union-Based) 2. 报错注入(Error-Based) 3. 布尔盲注(Boolean Blind) 4. 时间盲注(Time-Based&#xff0…

c语言 关键字--目录

下面是详细介绍的链接 1.c语言 关键字 2.typedef 关键字 3.volatile 关键字 4.register 关键字 5.const关键字用法 6.extern关键字 7.sizeof关键字

python爬虫爬取网站图片出现403解决方法【仅供学习使用】

基于CSDN第一篇文章,Python爬虫之入门保姆级教程,学不会我去你家刷厕所。 这篇文章是2021年作者发表的,由于此教程,网站添加了反爬机制,有作者通过添加cookie信息来达到原来的效果,Python爬虫添加Cookies以…

docker创建一个centOS容器安装软件(以宝塔为例)的详细步骤

备忘:后续偶尔忘记了docker虚拟机与宿主机的端口映射关系,来这里查看即可: docker run -d \ --name baota \ --privilegedtrue \ -p 8888:8888 \ -p 8880:80 \ -p 8443:443 \ -p 8820:20 \ -p 8821:21 \ -v /home/www:/www/wwwroot \ centos…

linux 使用nginx部署ssl证书,将http升级为https

前言 本文基于:操作系统 CentOS Stream 8 使用工具:Xshell 8、Xftp 8 服务器基础环境: nginx - 请查看 linux 使用nginx部署vue、react项目 所需服务器基础环境,请根据提示进行下载、安装。 1.下载证书 以腾讯云为例&#x…

日常开发中,iOS 性能调优我们怎么做?

日常开发中,iOS 性能调优我们怎么做?聊聊我用过的几款工具 最近在给一个 iOS 视频类 App 做性能优化,过程中踩了不少坑,也用了一些不错的工具,今天就以一个开发者视角随便聊聊我在调试过程中的一些经验。 一、性能问…

Redis ⑨-Jedis | Spring Redis

Jedis 通过 Jedis 可以连接 Redis 服务器。 通过 Maven 引入 Jedis 依赖。 <!-- https://mvnrepository.com/artifact/redis.clients/jedis --> <dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><versi…

【人工智能】解锁AI潜能:LM Studio多模型并行运行DeepSeek与开源大模型的实践指南

《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门! 解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 随着大语言模型(LLM)的快速发展,LM Studio作为一款本地化部署工具,以其简单易用的图形化界面和强大的模型管理能力受到广泛关注。本文深…

Node.js面试题

一、什么是Node.js&#xff1f; Node.js 是一个开源的跨平台 JavaScript 运行时环境&#xff0c;允许开发者在服务器端运行 JavaScript 代码。它基于 Chrome 的 V8 JavaScript 引擎构建&#xff0c;能够高效地处理 I/O 操作&#xff0c;适合构建高性能的网络应用。 异步非阻塞&…

Playwright MCP 入门实战:自动化测试与 Copilot 集成指南

什么是 MCP&#xff1f; MCP&#xff08;Model Context Protocol&#xff09; 是一种为大语言模型&#xff08;LLM&#xff09;设计的协议&#xff0c;MCP充当 LLM 与实际应用之间的桥梁或“翻译器”&#xff0c;将自然语言转化为结构化指令&#xff0c;使得模型可以更精确、高…

达梦DM数据库安装步骤

文章目录 1、下载并解压缩2、安装DM数据库2.1 运行安装程序2.2 选择语言与时区2.3 安装向导2.4 许可证协议2.5 Key文件2.6 选择组件2.7 安装位置2.8 安装前小结2.9 安装过程2.10 已完成2.11 初始化 3、配置实例3.1选择操作方式3.2创建数据库模版3.3指定数据库目录3.4数据库标识…

电商双11美妆数据分析(2)

接下来用seaborn包给出每个店铺各个大类以及各个小类的销量销售额 关于性别 接下来考虑性别因素&#xff0c;了解各类产品在男性消费者中的销量占比 男士的销量基本来自于清洁类&#xff0c;其次是补水类。而这两类正是总销量中占比最高的两类。 非男士专用中&#xff0c;补水…