网络原理-UDP和TCP

在传输层中有两个非常重要的协议,UDP和TCP,现在就来研究一下这两个协议。

UDP

报文格式

我们观察可以发现,里面UDP报文长度为2个字节,那么是多少呢?我们需要快速反应如下固定字节数据类型的取值范围:

字节大小有无符号取值范围
1个字节有符号-128-127
1个字节无符号0-255
2个字节有符号-32768-32767
2个字节无符号0-65535
4个字节有符号-21亿-21亿
4个字节无符号0-42亿

源端口:2个字节,无符号,取值0-65535.

目的端口:2个字节,无符号,取值0-65535.

UDP报文长度:2个字节,无符号,取值范围0-64k,也就是说一个UDP最多能传输64kb的数据,这在当今是一个很小的数字(现在一个文件动不动就几个G).

说明:

能否将这个长度变大呢?理论上可以,但是几乎无法做到。

理论上,我们只需要修改系统内核中udp的参数,将unsigned short改成int就可以增加长度,但是我们不能只修改自己电脑的,我们还得修改别人的,怎么说每个人都改呢???

不过我们还可以将数据拆分成多组进行传输或者使用tcp代替udp,tcp没有报文长度限制。

校验和:使用了一种简单粗暴的校验算法,把UDP数据报中的每个字节都依次进行累加。

说明:

为什么要使用校验和呢?因为网络传输本质上是光信号/电信号传输,会受到磁场,高能粒子的干扰,就有可能使传输的数据突变,即0变1,我们需要使用校验和来确保传输的数据没有变化。

一般UDP中校验和是将数据报中每个字节都累加,可能会溢出,但是不要紧,当接收方收到数据了后,再按照同样的方式进行累加,如果得到值一样,就是正确的。万一前面的字节值变小了,后面的变大了,一加一减没变,又该如何应对?这种情况是可能出现,但是概率极低,毕竟工程上有一些误差也能接受。

TCP

报文格式

 

 

序列号:给传输的数据进行编号。发送方每发送一次数据,序列号的值就累加一次该数据字节数的大小,可以用来解决乱序的问题。

乱序问题:

为了追求效率,数据会被进行分组,例如有一个2000字节的数据包,被分为两组1-1000、1001-2000,从A端发送到B端,但网络的路径非常多,这两组数据可能会走不同的路线,又因为每个路由器/交换机的繁忙程度不一样,转发的过程也就不一样,因此就不能保证先发先至了,此时我们需要搞清楚哪个数据在前,哪个数据在后,就可以根据序列号来确定。

确认应答号:用在接收方,表示期望下一次接受的数据的序列号,发送方收到这个确认应答号可以认为在这个序号前的数据都被接收了,用来解决丢包问题。

丢包问题:

由于网络的结构复杂,某一时刻某一路由器/交换机数据量非常多,就导致了设备非常繁忙,数据处理的排队时延会很大,此时就有可能采取丢弃策略,就产生了丢包现象,那为了知道丢了哪些包,需要通过确认应答号告诉对方,哪部分的数据没有收到。

首部长度:表示的是TCP报头的长度。TCP报头的前20个字节是固定的,选项部分可以有也可以没有,因此TCP报头的长度是可变的,取值范围为:0*4byte ~ 15 * 4 byte。

保留位:暂时不用,为以后升级留下空间。

标志位:

  • ACK:该位为1时,表示确认应答的为有效字段。

  • RST:该位为1时,表示TCP连接中出现异常必须强制断开连接。

  • SYN:该位为1时,表示希望建立连接,并在设置序列号字段的初始值。

  • FIN:该位为1时,表示不会有数据发送,希望断开连接。

特性

由于TCP中很多特性,在这列举比较熟知的。

一、确认应答

确认应答是保证”可靠性“最核心的机制

确认应答就是告诉对方我收到消息了。发送方发出一个数据包,如果接收方收到了,就返回一个数据包告诉发送方我收到了。

确认应答机制往往配合着确认序号与ACK标志位使用。当ACK标志位为1时,确认序号为有效值,此时这条报文就是一个应答报文,告诉发送方我这边收到了,发送方可以根据确认序号看看有没有丢包的情况。

二、超时重传

由于网络的情况非常复杂,避免不了出现一些丢包的现象,那又该如何处理呢?此时可以大致分为两类情况,一种是发送端发送的数据包丢了,另一种是接收端的应答数据包丢了。

情况一:

如果是发送端发送的数据包丢了,此时发送端就一直接收不到ACK数据包,我们可以通过设置一个超时时间,即过了这个时间还没有收到ACK的话,就再发一次数据包。

总的来说就是没收到应答,就再发一次。

情况二:

如果是接收端已经收到了这个数据,但是应答报文丢了,此时发送端无法区分是否是第一种情况,所以还是会进行重传,接收端就需要进行去重操作。然后再次发送一个应答报文。

如何去重?

使用序列号作为判定的依据。tcp会在内核中给每个socket对象都安排一个内存空间,相当于一个队列,收到的数据就会被放到这里面,并按照序号排列好(还解决了乱序的问题),当来了一个重复的数据以后,就可以根据索引值判断是否出现过了。


丢包本质上是一个概率事件,不可避免,而且随着重传的次数,概率会大幅降低。我们需要合理的设置超时时间。

具体数值可以手动配置,我们更应该去关注里面的策略。

超时时间不是一个固定的值,会随着超时轮次增加。如果好几次都没重传成功的话,说明此时网络本身的丢包率非常高,可能遇到了非常严重的故障,需要拉长一下重传时间,给网络恢复留有一个时间。超时重传的轮次也不是无限的,达到一定次数就会尝试重置tcp连接,设置RST标志位,如果RST报文也丢了,说明此时网络严重故障,那就会放弃连接。

三、连接管理

三次握手

TCP是面向连接的协议,所以使用TCP前必须先建立连接,而连接的建立是通过三次握手来进行的。不过三次握手本质上是"四次握手",只是将其中的两步合并成了一步。

ACK是应答报文,SYN是同步报文,表示申请建立请求。


为什么要进行三次握手?

1、验证通信路径是否通畅,双方的发送和接受能力是否正常

TCP要想保证可靠传输,就得先知道有没有路径以及路径是否通畅(网络拥堵会出现历史连接原因,造成资源的浪费),然后通过三次握手,确定双方是否有发送和接受的能力。只有确定了双方都有接收和发送的能力,才能进行后续的可靠传输。

2、协商必要的参数

通信的时候会涉及到一些参数,比如序列号。由于网络是时刻变化的,会出现先发后至的现象,这时我们可以通过序列号来判断这个消息是不是合法的,即可能这个数据是上一次的连接中的。


那是否可以只进行两次握手呢?四次是否可以?

如果值进行两次握手的话,B端就无法知道A端能否接受数据,以及自己的数据有没有发过去,也就无法保证参数进行了协商,即不能保证双方的序列号是同步,并且如果出现了网络较为拥塞的时候,建立连接的消息重发了好几次,服务器在第一次握手的时候就会建立连接,即创建了一个socket对象,造成了资源的浪费。

如果是进行四次握手的话,本质上就是将三次握手的第二次握手拆开来,而三次握手就可以建立可靠的连接了,多了反而也会浪费资源。

四次挥手

在进行通信后,由于前面的连接会消耗资源,因此我们还需要进行断开连接来释放资源。由于断开连接涉及到了四次通信,因此也被称为是四次挥手。

四次握手能变成三次握手吗?理论上是可以的,当我们调用socket.close方法足够快的时候,即收到关闭请求的后续没啥业务逻辑,就可以合并。但是一般服务器后续还有很多的收尾工作要处理,这时候close方法执行的时机比较慢,就不能合并了。

丢包问题

由于网络通信的复杂,可能会出现丢包,这时候怎么办呢?

一个原则,收不到回应就重传,重传多次还收不到,那就单方面断开连接。

如果第一次挥手丢了,那么就重传,一直收不到回应就断开连接。

如果第二次挥手丢了,由于客户端无法区分,客户端会重传FIN报文,跟第一次挥手丢了同理。

如果第三次挥手丢了,重传,一直收不到回应,就断开连接。

如果第四次挥手丢了,此时站在客户端的角度,客户端收到了服务器的FIN报文并已经发出ACK报文确认了,但是客户端还不能立马释放连接,因为还不能确定服务器是否收到,因此会等待一个2*MSL的时长,在此期间没收到重传的FIN报文,就可以释放连接了。如果丢包了,服务器会重传FIN报文,客户端也就可以回应ACK报文了。

四、滑动窗口

滑动窗口机制是用来提高TCP的传输效率,让TCP在保证可靠的前提下,效率别要太低。虽然滑动窗口能提升TCP的效率,但是这也是有限的,还是不可能比UDP高。

本质就是节省了应答时间。之前是每发一次数据就需要等待一个确认报文的时间,使用滑动窗口后,可以在等待确认报文的时间内,再多发几次数据。


丢包问题

在发数据的时候,丢包情况分为两种:1)数据报了 2)确认应答(ACK)丢了

1)数据丢了

由于前面的确认应答机制,我们TCP协议中的确认序号字段会记录当前发到哪个数据了,如果前面某一个数据丢了,确认序号不会改变,依旧和上一次应答的确认序号是一样的,后面客户端连续收到了服务器索要的相同确认序号的数据时,客户端就明白了丢了哪部分数据,然后就可以进行重传。

2)确认应答丢了

确认应答丢了并不要紧,只要后续确认应答的序号比前面确认应答的序号大的话,就可以理解为,前面的数据都已经接收到了,如果所有ACK都丢了,说明网络出现了重大故障,此时也不满足网络可靠的前提条件了。

五、流量控制

流量控制是作为滑动窗口的补充,理论上滑动窗口越大,传输效率就越高,但是当窗口大小达到一定程度后,接收方可能就处理不过来了,或者说网络传输上的某条链路就处理不过来了,这样就会出现丢包,就得进行重传,结果适得其反了。因此我们需要进行流量控制,让发送方慢一点~

流量控制就是根据接收方的接收能力,来限制发送方的速度,即限制窗口大小。当接收方接收数据的时候,会先将数据存储在缓存区中,因此可以是用缓存区中的剩余空间大小来作为窗口的大小,即修改TCP的中窗口大小字段。

大致流程:

首先客户端先发送一下数据,看看窗口大小多少合适,然后根据窗口大小发送数据,当窗口大小为0的时候就不发数据,期间会发送窗口探测包,来询问服务器啥时候有空?一旦发现不是0了以后,就继续开始发数据。这样接收方可以根据窗口大小来限制发送方的传输速度了。

六、拥塞控制

上述的流量控制是针对接收方的处理能力来判断当前的窗口大小,但是由于在传输的过程中会经过许多节点(路由器/交换机),那么这些中间节点的处理能力是否能达到窗口大小呢?

由于路过哪些节点,在一开始的时候是无法确定的,因此设计TCP的大佬们选择使用"实验"的方式来测试路径节点的接收能力,然后综合分析计算得出一个值,后续再发送数据的速度就不应该超过这个值(木桶效应)。

拥塞控制具体是这样展开的:

1.慢启动:刚开始通信的时候使用一个小窗口,如果传输顺利,没有丢包就会进行扩大窗口。

2.指数增长:在传输顺利后,拥塞窗口大小就会指数增长。

3.线性增长:当指数增长到一个阈值的时候,就会从指数增长转变为线性增长。

4.拥塞窗口回归小窗口:在窗口增长的过程中,如果传输过程中出现丢包了,说明此时发送的速率接近当前网络的极限,此时会把窗口调整为最初的小窗口并将指数增长的阈值变小,然后继续重复上述的过程。

因此还可以得出一个结论:实际发送的窗口大小不光要考虑接收方的处理能力,还要考虑中间节点的处理能力。

实际发送方的窗口= min (拥塞窗口, 流量控制窗口)

七、延时应答

延时应答也是为了增大滑动窗口的大小,从而挺高传输效率而提出的。

延时应答通过在返回ACK应答报文的时候,尽量慢一点,利用拖延出来的一点点时间,让接收方多处理一些数据,这样接收方的接收缓冲区的空间就更大了,下一次就能接收更多的数据。

八、捎带应答

捎带应答是在延迟应答的基础上,引入的进一步提高效率的方式。

延迟应答是让ACK报文传输的时机更慢,我们不仅可以让接收方利用这段时间处理缓存中数据,还可以让接收方做出响应的同时再带上ACK报文(类似将四次握手合并成三次握手)。

之前所提到的四次挥手也有可能变成三次,主要是通过延时应答和捎带应答完成的。在第二挥手的时候进行延时应答,然后跟第三次挥手一起发送给对方,而数据包从两个合并成一个,效率会有明显的提升,因为每次传输数据都会进行封装分用以及传输时延都会花费不少时间。

九、面向字节流——粘包问题

由于TCP是面向字节流的,所接收到的数据包会按照一个字节一个字节的存储在缓存区中,如果我们不认为的进行约定,那么就无法区分一个数据的结尾是哪。

如上所示:

对于发送方来说,发送了3个数据报,AAA为一个应用层数据报,BBB是一个应用层数据报,CCC是一个应用层数据报,但是接收方可区分不了,三个数据报都粘在一起了,很有可能后续会理解错发送方的意思,比如将这三个数据包理解为了AAAB, BBC, CC,就出现了bug。

此时就只能在应用层面来处理这个问题了。如:

  1. 在应用层协议中引入分隔符区分包之间的边界。例如:以\n作为一个数据包的结束标志。

  2. 在应用层协议中引入包长度区分包之间的边界。

十、异常情况处理——心跳包

在实际生活中,会出现许多不可抗力的因素,比如电源被家长关了、网线被人拔了等,不过这些大差不差,可以分为四大类。

1、进程崩溃

当进程崩溃了,进程所持有的PCB中的文件描述符表也就被释放了,即相当于调用了socket.close方法,崩溃的一方在内核中就会发出FIN,就变成了四次挥手了,此时也就和进程的正常退出没啥区别了。

2、主机关机

电脑在正常关机的时候,会先结束掉所有的进程,后续就跟进程崩溃的处理一样了(如果没挥手完也没关系 ,也就演变成了丢了某一次挥手)。

3、主机掉电

如果是台式机的话,一旦拔掉电源,电脑就立马黑屏了,根本不会给操作系统留有反应的空间。此时又分为了两种情况:

a) 如果接收方突然断电了,那么发送方就无法接收到ACK,此时发送方会进行超时重传,如果一直重传失败,就会发送复位报文(RST),尝试重置连接,如果失败了,就会单方面释放连接了。

b)如果发送方突然断电了,接收方无法区分发送方是等一会发送呢,还是不发了,此处就会涉及到"心跳包",接收方就会周期性的给对方发一个不携带任何业务数据的tcp数据报,发起这个这个包的目的,就是为了触发ACK确认对方是否正常工作。

4、网线断开

如果是网线断开的话,其实也跟主机掉电基本类似。

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

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

相关文章

Jenkins服务器IP更换,Jenkins URL地址更换

服务器的网络地址发生变动,修改jenkins服务器IP地址后,jenkins网页能够打开,但是job中的配置钩子没有自动改变,如图所示: 经过查询资料了解,需要修改jenkins本地化配置地址才可以显示正确: 1、…

初识ansible变量及实例配置

目录 1、为什么要使用变量 2、变量分类 3、 变量详解 3.1 vars,vars_files , group_vars 3.1 .1 vars 剧本中定义变量 3.1.2 vars_file 将变量存放到一个文件中,并在剧本中引用 3.1.3 group_vars 创建一个变量文件给某个组使用 实例1-根据不同的主机…

Java关键字和API

1 this和super关键字 1.this和super的意义 this:当前对象 在构造器和非静态代码块中,表示正在new的对象 在实例方法中,表示调用当前方法的对象 super:引用父类声明的成员 无论是this和super都是和对象有关的。 2.this和sup…

通过实例学C#之序列化与反序列化XmlSerializer类

简介 可以将类序列化成xml文件,或者将xml文件反序列化成类对象,一般用于保存或加载项目参数。 构造函数 XmlSerializer() 不使用函数创建一个xmlSerializer对象。 XmlSerializer(Type type) 使用type对象创建一个xmlSerializer对象,注意&…

【001_IoT/物联网通信协议基础: HTTP、Websocket、MQTT、AMQP、COAP、LWM2M一文搞懂】

001_IoT/物联网通信协议基础: HTTP、Websocket、MQTT、AMQP、COAP、LWM2M一文搞懂 文章目录 001_IoT/物联网通信协议基础: HTTP、Websocket、MQTT、AMQP、COAP、LWM2M一文搞懂创作背景通信模型ISO/OSI七层模型 和 TCP/IP四层模型网络通信数据包格式(Ethernet II&…

20240421阿夏的CSDN创作纪念日(3周年)

缘 提示:可以和大家分享最初成为创作者的初心 3年前我写下第一篇CSDN,开启了Python研究之旅win10系统64位( 惠普)台式电脑自动开机、关机图文详细解(一)_惠普主板设置自动开机-CSDN博客文章浏览阅读4.2k次…

深入OceanBase内部机制:资源隔离实现的方式总结

码到三十五 : 个人主页 心中有诗画,指尖舞代码,目光览世界,步履越千山,人间尽值得 ! 目录 1. 为何HTAP需要资源隔离2. OceanBase的资源隔离机制概述租户间资源隔离租户内资源隔离物理资源隔离大查询请求的隔离优先级…

4月21敲一篇猜数字游戏,封装函数,void,无限循环,快去体验体验

今天敲一篇猜数字游戏 目录 今天敲一篇猜数字游戏 1.打开先学goto语句: 2.开干: 首次我们学习随机数: 讲解一下: 改用srand; 加入时间变量: 获取时间:哈​编辑 3.我本来想已近够完美了&#xff0…

Flink学习(七)-单词统计

前言 Flink是流批一体的框架。因此既可以处理以流的方式处理,也可以按批次处理。 一、代码基础格式 //1st 设置执行环境 xxxEnvironment env xxxEnvironment.getEnvironment;//2nd 设置流 DataSource xxxDSenv.xxxx();//3rd 设置转换 Xxx transformation xxxDS.…

Spring Boot中接收各种各样的参数

一、接收json参数&#xff0c;封装为Map 1.1、核心代码 /*** 接收json参数&#xff0c;封装为Map* param servletRequest* return* throws Exception*/ PostMapping("/getParam") public R getParam(HttpServletRequest servletRequest) throws Exception {Map<…

Bootstrap 5 保姆级教程(十二):弹出框 消息弹窗

一、弹出框 1.1 创建弹出框 通过向元素添加 data-bs-toggle"popover" 来来创建弹出框。 title 属性的内容为弹出框的标题&#xff0c;data-bs-content 属性显示了弹出框的文本内容&#xff1a; 注意: 弹出框要写在 JavaScript 的初始化代码里。 以下实例可以在文…

投入产出表的分析要点有哪些

投入产出分析是利用投入产出表、投入产出系数和投入产出模型&#xff0c;对国民经济各部门之间的技术经济联系和影响进行分析的一种经济数据分析方法。 一、什么是投入产出表 我国的投入产出表是描述国民经济中各种产品的来源与使用去向的棋盘式平衡表 , 是产品部门 产品部门…

【已解决】电脑设置notepad++默认打开txt

1、以管理员的方式打开notepad 步骤&#xff1a;打开设置 -> 首选项 -> 文件关联 2、 设置Notepad默认打开 按照以下步骤将Notepad设置为默认打开.txt文件&#xff1a; 右键单击任何一个.txt文件。选择“属性”。在“常规”选项卡中&#xff0c;找到“打开方式”&#…

【Interconnection Networks 互连网络】Dragonfly Topology 蜻蜓网络拓扑

蜻蜓拓扑 Dragonfly Topology 1. 拓扑参数2. Topology Description 拓扑描述3. Topology Variations 拓扑变体 蜻蜓拓扑 Dragonfly Topology 1. 拓扑参数 Dragonfly拓扑参数&#xff1a; N N N: 网络中终端(terminal)的总数量 p p p: 连接到每个路由器的终端数量 a a a: 每…

VR全景:为户外游玩体验插上科技翅膀

随着VR全景技术的愈发成熟&#xff0c;无数人感到惊艳&#xff0c;也让各行各业看到了一片光明的发展前景。尤其是越来越多的文旅景区开始引入VR全景技术&#xff0c;相较于以往的静态风景图&#xff0c;显然现在的VR全景结合了动态图像和声音更加吸引人。 VR全景技术正在逐步改…

Dijkstra算法求最短路

Dijkstra算法可以在图中寻找一个节点&#xff08;称为“源节点”&#xff09;到所有其它节点的最短路径。 文章目录 前言 一、Dijkstra算法是什么&#xff1f; 二、问题介绍 三、朴素版Dijkstra算法 1.图的存储 2.算法实现 四、使用步骤 1.代码如下&#xff08;示例&#xff09…

Linux的UDEV机制

udev 机制引入&#xff1a; 手机接入Linux热拔插相关 a. 把手机接入开发板 b. 安装adb工具&#xff0c;在终端输入adb安装指令&#xff1a; sudo apt-get install adb c. dmeg能查看到手机接入的信息&#xff0c;但是输入adb devices会出现提醒 dinsufficient permissions for …

【Java】HashMap、HashTable和ConcurrentHashMap的区别

文章目录 区别一、HashMap1.1基本定义与特性1.2工作原理与实现1.3常用方法1.4性能与优化 二、HashTable三、ConcurrentHashMap3.1基本特点3.2实现原理3.3常用方法3.4适用场景3.5性能优化 HashTable、HashMap和ConcurrentHashMap之间的区别主要体现在线程安全、继承关系与实现接…

kaggle 泰坦尼克号2 得分0.7799

流程 导入所要使用的包引入kaggle的数据集csv文件查看数据集有无空值填充这些空值提取特征分离训练集和测试集调用模型 导入需要的包 import pandas as pd import numpy as np import matplotlib.pyplot as plt import seaborn as sns import warnings warnings.filterwarni…

从C到JAVA之学习JAVA的第一周笔记

文章目录 java语言概述JDK与JRE编写执行过程第一份java代码解读编写编译运行其他 注释三种注释方法 java API文档关键字标识符数据类型基本数据类型自动类型提升规则引用数据类型 string概述String与基本数据类型的变量间的运算 运算符键盘录入运行控制语句数组定义与静态初始化…