网络原理-UDP/TCP详解

news2024/11/17 11:38:27

一. UDP协议

UDP协议端格式

由上图可以看出,一个UDP报文最大长度就是65535. 

• 16位长度,表示整个数据报(UDP首部+UDP数据)的最大长度(注意,这里的16位UDP长度只是一个标识这个数据报长度的字段,并不是这个数据报传输的数据)

• 如果校验和出错,就会直接丢弃。

 校验和:通过网线传输时,电信号使用高低电平来表示0和1.。但是,如果外部环境干扰,就有可能导致低电平->高电平,高电平->低电平,造成比特翻转=>数据就传输错了。校验和就是通过数据报中的数据内容通过计算得到的。值得注意的是:如果校验和不对,此时你的数据一定不对,如果校验和对,但是数据也有一定概率是错误的。

面向数据报:应用层交给UDP长的报文,UDP原样发送,既不会拆分,也不会合并。

用UDP传输100个字节的数据报:

如果一次发送端发送100个字节,那么接收端也必须一次接收100个字节;而不能循环10次接收,每次接收10个字节。

缓冲区:UDP只有接收缓冲区,没有发送缓冲区

UDP没有真正意义上的发送缓冲区,发送的数据会直接交给内核,由内核将数据传给网络层协议进行后续的传输动作;

DUP具有接收缓冲区,但是这个接收缓冲区不能保证收到的DUP报的顺序和发送DUP报的顺序一致;如果缓冲区满了,再到达的DUP数据就会被丢弃;

二. TCP协议

TCP协议段格式:

2.1 TCP原理 

2.1.1 确认应答机制

TCP 将每个字节的数据都进行了编号。即位序列号。

发送方的序号为最后一个字节的编号,确认序号为无意义的数据;

接收方的序号和发送方的序号无关,确认序号为接收数据的序号+1。

(在接收缓冲区中,优先级队列通过序号来确定数据的发送先后顺序 )

接收方就可以通过ack的确认序号,告诉发送方哪些数据已经收到了。

2.1.2 超时重传机制

主机A发送数据给B之后,可能因为网络拥堵等原因,数据无法到达主机B;

如果主机A在一个特定时间间隔内没有收到B发来的确认应答,就会重发。

但是,主机A未收到B发来的确认应答,也可能是因为主机B收到了数据,但是ACK丢失了;

因此若ACK丢失了,主机B会收到很多重复数据。那么TCP协议需要能够识别哪些包是重复的包,并且把重复的丢弃掉。这时候我们就可以利用前面提到的序号来达到去重的效果。

超时重传后,重复发送的数据报仍可能会丢失,TCP为了保证无论在任何环境下都能比较高性能的通信,因此会动态的计算这个最大超时时间。

如果重发一次,仍得不到应答,TCP就会将这个超时时间延长后再重发,在不停的延长超时时间后,当累积到一定的重传次数后,TCP就会重置连接,如果重置连接失效,TCP就会关闭连接,放弃网络通信。

2.1.3 连接管理机制(三次握手,四次挥手)

建立连接:三次握手

握手指的是通信双发,进行一次网络交互,相当于客户端和服务器之间,通过三次交互,建立了连接关系。 

syn称为同步报文段。意思就是一方要向另一方,申请连接。

在报文头部中有6个特殊的比特位,如果设为1,则表示特定含义。

其中第二位,是ACK,如果这一位为1,表示当前TCP数据报是一个应答报文;

其中第五位,是SYN,如果这一位为1,表示当前TCP数据报是一个同步报文;

如果一个TCP数据报,第二位和第五位都是1,则当前这个报文时SYN+ACK

三次握手这个过程,本质上时投石问路,验证了客户端和服务器,各自的发送能力和接收能力是否正常 

断开连接:四次挥手

FIN:结束报文段

四次挥手中的ack和fin是否可以合并?

在三次握手中,ack和syn时同一时刻触发的(都是内核来完成的)

四次挥手,ack和fin则是在不同时机触发的。

ack是内核完成的,会在收到fin的时候第一时间返回

fin则是应用程序代码控制的。在调用到socket的close方法时候才会出发fin

finally{ 
    //thread.sleep(1000);
    socket.close();
}

这个close的执行时机,可能是立即,也可能是隔很久,却决于你的代码怎么写。

如果立即 close,趁着刚才ack还没发呢,这里就可以合并,如果是隔很久再close,此时fin就只能单独发了。

注:这里的close只是进程关闭了,但是连接(连接是内核维护的)还在,客户端发送的ack,服务器仍然可以收到。

2.1.4 滑动窗口(效率机制)

对于每一个发送的数据段,都要给一个ACK确认应答,收到ACK后再发送下一个数据段。.由于这样的一收一发的方式性能较低,那么我们一次发送多条数据,就可以大大的提高性能。(其实是将多个段的等待时间重叠在一起了。

窗口大小指的是无需等待应答而可以继续发送数据的最大值.上图的窗口大小就是4000个字节(4个段)。

发送前四个段的时候,不需要等待任何ACK,直接发送。

操作系统内核为了维护这个滑动窗口,需要开辟发送缓冲区来记录当前还有哪些数据没有应答;只有确认应答过的数据,才能从缓冲区删掉。

• 窗口越大,则网络的吞吐率就越高。

如果出现了丢包的情况,如何重传?分两种情况:

情况一:数据包已经抵达,ACK被丢了。

这种情况下,部分ACK丢了并不要紧,因为可以通过后续的ACK进行确认。如果1001的 ACK没有接收到,收到了2001的ACK,那么就说明已经接收到了2001以前的数据。

情况二:数据包直接丢了。 

当某一段报文丢失之后,发送端会一直收到1001这样的ACK,就像是在提醒发送端“我想要的是"1001"一样;

当发送端主机连续收到三次同样的“1001”这样的应答,就会将对应的数据1001~2000重新发送

这个时候接收端收到了1001之后,再次返回的ACK就是7001了,因为2001~7000接收端其实之前就已经收到了,被放到了接收端操作系统内核的接收缓冲区中。

2.1.5 流量控制(安全机制)

接收端处理数据的速度是有限的。如果发送端发送的太快,导致接收端的缓冲区被打满,这个时候如果发送端继续发送,就会造成丢包,继而引起丢包重传等一些列连锁反应。 

因此TCP支持根据接收端的处理能力,来决定发送端的发送速度。这个机制就叫做流量控制

• 接收端将自己可以接收的缓冲区大小放入TCP首部中的“窗口大小”字段,通过ACK端通知发送端,此时发送端就可以根据这个窗口大小来批量发送这些数据了。

• 接收端一旦发现自己的缓冲区快满了,就会将窗口大小设置成一个更小的值通知给发送端;

• 发送端接收到了这个窗口之后,就会减慢自己的发送速度

• 如果接收端缓冲区满了,就会将窗口设置为0;这时发送方就不再发送数据,但是仍需要定期发送一个窗口探测数据段,使接收端把窗口大小告诉发送端。

上述过程是把返回的窗口大小,当作实际的窗口,实践中可能会有出入。

发送方的窗口大小=min(流量控制,拥塞控制)。

2.1.6 拥塞控制(安全机制) 

虽然TCP有了滑动窗口这个大杀器,能够高效可靠的发送大量的数据.但是如果在刚开始阶段就发送大量的数据,仍然可能引发问题.

因为网络上有很多的计算机,在传输的过程中,需要经历许多的节点,可能当前的网络状态就已经比较拥堵了,但是此时在不清楚当前网络状态下,贸然发送大量的数据,是很有可能引起雪上加霜的.于是,不管在客户端与服务器之间是经历怎样的路径,把这个路径当做黑盒一样的东西,每次发送不同数量的请求,来试验出最佳的发送窗口.

TCP引入 慢启动 机制,先发送少量的数据,探探路,摸清当前的网络拥堵状态,再决定按照多大的速度传输数据

• 发送开始的时候,定义拥塞窗口大小为1

• 每次收到一个ACK应答,拥塞窗口加1

• 每次发送数据包的时候,将拥塞窗口和接收端主机反馈的窗口大小作比较,取较小的值作为实际发送的窗口

 为了让拥塞窗口不增长的那么快,变引入了一个叫做慢启动的阈值,当拥塞窗口超过这个阈值的时候,不再按照指数的方式增长,而是按照线性方式增长

• 当TCP开始启动的时候,慢启动阈值等于窗口最大值;

• 在每次超时重发的时候,慢启动阈值会变成原来的一般,同时拥塞窗口重置回1.

2.1.7 延迟应答

如果接受数据的主机立刻返回ACK应答,这时候返回的窗口肯能比较小.

• 假设接收缓冲区为1M,一次收到了500k的数据,如果立刻应答,返回的窗口就是500k

• 但实际上可能处理端处理的速度很快,10ms之内就把500k的数据从缓冲区消费掉了

• 在这种情况下,接收端处理还远没有达到自己的极限,即使窗口再放大一些,也能处理过来

• 如果接受端稍微等一会再应答,比如等待200ms再应答,那么这个时候返回的窗口大小就是1M

窗口越大,网络吞吐量就越大,传输效率就越高.我们的目标是在保证网络不拥塞的情况下尽量提高传输效率.

但是并不是所有的包都可以延迟应答

数量限制:每隔N个包就应答一次;

时间限制:超过最大延迟时间就应答一次

具体的数量和超时时间,操作系统不同也有差异;一般N取2,超时时间取200ms(根据业务需求可自定义)

2.1.8 捎带应答

在延迟应答的基础上,我们可以发现,很多情况下,客户端服务器在应用层也是一发一收的.意味着客户端给服务器说了"How are you" , 服务器中程序处理过请求后也会给客户端返回一个"Fine,thank you" , 那么这个时候ACK就可以搭顺风车,和服务器回应的"Fine, thank you" 一起返回给客户端 

 上述ACK是内核收到数据报后直接返回的,Fine....是应用程序,通过write写的数据,通过一系列代码执行到才返回,这俩时机本来是不同的.但是延时应答,使此时的ACK 就可能稍等一会再发送就很有可能和response 合并成一个数据报.四次挥手,有可能是三次挥手,就是捎带应答起到的效果.

2.2 粘包问题

在TCP协议头中,没有如同UDP一样的“报文长度”这样的字段,但是有一个序号这样的字段,站在传输层的角度,TCP是一个一个报文过来的。按照序号放在缓冲区中。站在应用层的角度,看到的只是一串连续的字节数据。那么应用程序看到了这么一连串的字节数据,就不知道从哪个部分开始到哪个部分结束,是一个完整的数据包。

如何解决粘包问题?归根结底就是一句话,明确两个包之间的边界。

• 对于定长的包,保证每次都按照固定大小读取即可;例如上面的Request结构,是固定大小的,那么就从缓冲区从头开始按sizeof(Request) 依次读取即可

对于变长的包,可以定义分隔符,来区分包(应用层协议,是程序员自己来定的,只要定义保证分隔符不和正文冲突即可)

对于变长的包,还可以在包头的位置,约定一个包总长读的字段,从而知道了包的结束位置

对于UDP协议来说,是否也存在“粘包问题”?

• 对于UDP,如果还没有上层交付数据,UDP的报文长度仍然在。同时,UDP是一个一个把数据交付给应用层。就有很明确的数据边界。

•  站在应用层的角度,使用DUP的时候,要么收到完整的UDP报文,要么不收,不会出现“半个”的情况。

2.3 TCP异常情况

2.3.1 进程关闭/进程崩溃

进程没了,socket 是文件,随之被关闭,虽然进程没了,但是连接还在,仍然可以继续四次挥手

2.3.2 主机关机(正常流程关机)

先杀死所有的用户进程,然后就和进程关闭一样。

虽然可以出发四次挥手,如果能够在关闭之前完成更好。

如果没有发完,比如,对方发的 fin 过来了,咱们没来得及ack就关机了,此时对端就会重传fin,重传几次之后,发现都没有ack,尝试重置连接,如果还不行,就直接释放连接。

2.3.3 主机掉电(把电源)

瞬间机器就关了,来不及进行任何挥手操作。此时分两种情况:

1)对端是发送端

对端就会收不到ack=>超时重传=>重置连接=>释放连接

2)对端是接收端

对端是没法立即知道,你这边是还没来得及发新的数据,还是直接没了。即使发送端没有写入操作,TCP自己也内置了一个保活机制“心跳包”。虽然是接收端,但是接收端会定期给发送端发送一个心跳包(ping),正常情况下就会返回一个(pong),如果每个 ping 都有及时的 pong,这个时候就说明当前对端的状态良好,如果 ping 过去之后,没用 pong ,说明心跳没了,这边怕是打概率挂了(pong也有概率丢的,因此会连续几次都丢了才会判定连接断开)。

注:发送方也是有心跳包的,但是通过对方返回的ack来判定会更快一些。

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

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

相关文章

[Android]修改应用包名、名称、版本号、Icon以及环境判断和打包

1.修改包名 在Android Studio中更改项目的包名涉及几个步骤: 打开项目结构: 在Android Studio中,确保您处于Android视图模式(在左侧面板顶部有一个下拉菜单可以选择)。 重命名包名: 在项目视图中,找到您的包名&…

Linux如何修改主机名(hostname)(亲测可用)

文章目录 背景Linux如何修改主机名(hostname)方法方法1. 使用 hostnamectl 命令示例 2. 编辑 /etc/hostname 文件注意事项 背景 我创建虚拟机的时候没设置主机名,现在显示localhost,有点尴尬😅: 需要重新设…

深入了解JVM和垃圾回收算法

1.什么是JVM? JVM是Java虚拟机(Java Virtual Machine)的缩写,是Java程序运行的核心组件。JVM是一个虚拟的计算机,它提供了一个独立的运行环境,可以在不同的操作系统上运行Java程序。 2.如何判断可回收垃圾…

单链表按位序与指定结点 删除

按位序删除(带头结点) #define NULL 0 #include<stdlib.h>typedef struct LNode {int data;struct LNode* next; }LNode, * LinkList;//按位序删除&#xff08;带头结点&#xff09; bool ListInsert(LinkList& L, int i, int& e) {if (i < 1)return false;L…

【Java 进阶篇】JQuery DOM操作:轻松驾驭网页内容的魔法

在前端开发的舞台上&#xff0c;DOM&#xff08;文档对象模型&#xff09;是我们与网页内容互动的关键。而JQuery作为一个轻量级的JavaScript库&#xff0c;为我们提供了便捷而强大的DOM操作工具。在本篇博客中&#xff0c;我们将深入探讨JQuery的DOM内容操作&#xff0c;揭开这…

基于Matlab+ AlexNet神经网络的动物识别系统

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 基于Matlab和AlexNet神经网络的动物识别系统可以用于自然图像识别等场景&#xff0c;以下是一个基本的介绍设计步骤…

ARM64 linux并发与同步之内存屏障

1.2 内存屏障 1.2.1 概念理解 原理部分比较苦涩难懂&#xff0c;我们先不过多详细介绍这部分的由来和经过&#xff0c;接下来着重讲解什么用途和实现&#xff1b; ARM64架构中提供了3条内存屏障指令。 数据存储屏障(Data Memory Barrier, DMB)指令。数据同步屏障(Data Synch…

Thinkphp8 - 连接多个数据库

// 数据库连接配置信息connections > [mysql > [// 数据库类型type > mysql,// 服务器地址hostname > 127.0.0.1,// 数据库名database > thinkphp,// 用户名username > env(DB_USER, root),// 密码password >…

Yolo自制detect训练

Install 把代码拉下来 GitHub - ultralytics/yolov5 at v5.0 然后 pip install -r requirements.txt 安装完了,运行一下detect.py即可 结果会保存在对应的目录下 Intro ├── data:主要是存放一些超参数的配置文件(这些文件(yaml文件)是用来配置训练集和测试集还有验…

clouldcompare工具使用

文章目录 1.界面1.1 布局1.3 视觉显示方向1.4 放大镜1.5 建立旋转中心2.快速入门2.1 剪裁2.2 多点云拼接 1.界面 1.1 布局 参考&#xff1a;https://blog.csdn.net/lovely_yoshino/article/details/129595201 1.3 视觉显示方向 1.4 放大镜 1.5 建立旋转中心 2.快速入门 2.1 …

腾讯域名优惠卷领取

腾讯域名到到期了&#xff0c;听说申请此计划&#xff0c;可获得优惠卷&#xff0c;看到网上5年域名只需要10元&#xff0c;姑且试试看。 我的博客即将同步至腾讯云开发者社区&#xff0c;邀请大家一同入驻&#xff1a;https://cloud.tencent.com/developer/support-plan?in…

UE地形系统材质混合实现和Shader生成分析(UE5 5.2)

前言 随着电脑和手机硬件性能越来越高&#xff0c;游戏越来越追求大世界&#xff0c;而大世界非常核心的一环是地形系统&#xff0c;地形系统两大构成因素&#xff1a;高度和多材质混合&#xff0c;此篇文章介绍下UE4/UE5 地形的材质混合方案----基于WeightMap混合。 材质层 …

每日一题(LeetCode)----数组--长度最小的子数组

每日一题(LeetCode)----数组–长度最小的子数组 1.题目&#xff08; 209.长度最小的子数组&#xff09; 给定一个含有 n 个正整数的数组和一个正整数 target 。 找出该数组中满足其总和大于等于 target 的长度最小的 连续子数组 [numsl, numsl1, ..., numsr-1, numsr] &…

敏捷开发是什么?敏捷开发流程是怎么样的?

1. 什么是敏捷开发&#xff1f; 敏捷开发是一种迭代、增量式的软件开发方法&#xff0c;旨在通过灵活、协作和快速响应变化的方式&#xff0c;提高开发团队的效率和产品的质量。相较于传统的瀑布式开发模型&#xff0c;敏捷开发更加注重用户需求的响应和团队协作&#xff0…

elastic-job 完结篇

一 elastic-job 1.1 案例场景分析 1.设置4个分片&#xff0c;10秒执行一次。 分片弹性扩容缩容机制测试&#xff1a; 测试1&#xff1a;测试窗口1不关闭&#xff0c;再次运行main方法查看控制台日志&#xff0c;注意修改application.properties中的 server.port&#xf…

7.运算符

目录 一.算数运算符 1、算术运算符 2、比较运算符 1、等号()用来判断数字、字符串和表达式是否相等。 2、安全等于运算符(<>) 3、不等于运算符(<>或者!) 4、小于或等于运算符(<) 5、小于运算符(<) 6、IS NULL(IS NULL)&#xff0c;IS NOT NULL 运算…

删除杀软回调 bypass EDR 研究

01 — 杀软或EDR内核回调简介 Windows x64 系统中&#xff0c;由于 PatchGuard 的限制&#xff0c;杀软或EDR正常情况下&#xff0c;几乎不能通过 hook 的方式&#xff0c;完成其对恶意软件的监控和查杀。那怎么办呢&#xff1f;别急&#xff0c;微软为我们提供了其他的方法&a…

2352 智能社区医院管理系统JSP【程序源码+文档+调试运行】

摘要 本文介绍了一个智能社区医院管理系统的设计和实现。该系统包括管理员、护工和医生三种用户&#xff0c;具有社区资料管理、药品管理、挂号管理和系统管理等功能。通过数据库设计和界面设计&#xff0c;实现了用户友好的操作体验和数据管理。经过测试和优化&#xff0c;系…

CentOS7、CentOS8 如何修改ip信息(修改网络信息)(无图形界面)(亲测可用)

文章目录 CentOS 7方法一&#xff1a;使用 nmcli 命令方法二&#xff1a;编辑配置文件&#xff08;我的CentOS7是使用这种方法&#xff0c;亲测可用&#xff09; CentOS 8方法一&#xff1a;使用 nmcli 命令方法二&#xff1a;编辑配置文件 在 CentOS 系统中&#xff0c;如果你…

二分图判定和二分图最大匹配

1.二分图的定义 二分图是一种特殊的无向图&#xff0c;它的节点可以被划分为两个互不相交的集合&#xff0c;使得同一集合中的任意两个节点之间没有边相连&#xff0c;而不同集合中的节点之间都有边相连。 换句话说&#xff0c;如果一个无向图可以被划分为两个集合&#xff0…