网络原理-UDP/TCP协议

协议

在网络通信中,协议是非常重要的一个概念,在下面,我将从不同层次对协议进行分析.

应用层

IT职业者与程序打交道最多的一层,调用系统提供的API写出的代码都是属于应用层的.

应用层中有很多现成的协议,但是更多的,我们需要根据实际情况来进行制作自定义协议.

自定义协议(网络传输的数据要怎么使用,数据是什么样的格式,里面包含什么内容)

自定义协议,需要约定好以下两个方面的内容:

1.服务器和客户端之间要交互哪些信息~~(客户端按照上述约定发送请求,服务器按照上述约定来解析请求)

2.数据的具体格式(服务器按照上述约定来构造响应,客户端也按照上述约定来解析响应)

举一个简单的例子:

1.请求,约定按照行文本的格式来进行表示,

userid,position\n  一个请求以\n为结尾.多个字段之间以,分割

1000,[经纬度]\n

2.响应,也是用行文本来进行表示,一个响应可能会包含多个商家,每个商家都要占一行.每个商家都要返回id,名称,图片,评分,简介(若干行之后,使用空行作为所有数据的结束标记)

(下面的一系列内容是同一个响应的数据)

1001,张亮麻辣烫,[logo图片地址],4.8非常好吃的麻辣烫\n

1002,魏家凉皮,[logo图片地址],4.7,很好吃的\n

\n

客户端和服务器之间往往需要进行交互的"结构化数据"(数据是一个结构体/类,包含许多属性)

网络传输的数据其实是"字符串""二进制bit流"

约定协议的过程,就是把结构化的数据转换成字符串/二进制比特流的过程

把结构化数据转换成字符串/二进制比特流 这个操作称为序列化

把字符串/二进制比特流还原成结构化数据 这个操作称为反序列化

序列化/反序列化具体要组织成什么样的格式,这里包含哪些信息~~

约定好这两件事的过程就是自定义协议的过程.

1.XML协议格式

请求:

<request>

  <userId>1000</userId>

  <position>[经纬度]</postion>

</request>

响应:

<response>

  <shops>

    <shop>

        <id>1001</id>

         <name>张亮麻辣烫</name>

   </shop>

  </shops>

</response>

这里的标签是成对出现的,<userId>成为开始标签,</userId>成为结束标签,开始标签和结束标签中间夹着的就是标签的值,表现也可以嵌套,这里标签的名字,标签的值标签的嵌套都是自定义的.

优点:可读性和扩展性提高了很多,后续要是增加一个属性,对已有代码影响不大,代码中可以按照名字获取标签的值,新增添的标签对已有代码影响不大

缺点:整个数据过于冗杂,冗余信息过多,标签占据的空间反而比数据本身更多了,尤其是网络传输的时候,这些数据都是要通过网络传输的(需要消耗带宽)

2.json协议格式

请求

{

         userId:1000,

        position:[经纬度]

}

响应

[

{

        id:1001,

        name:"张亮麻辣烫"

},

{

        id:1002,

        name:"魏家凉皮"

}

]

json是以键值对结构,键和值之间使用:分割,

键值对之间使用,分割

把若干个键值对使用{}括起来,此时就是一个json对象

,还可以把多个json对象放到一起,使用,分割开,并且使用[]整体括起来,就形成了一个json数组

优点:可读性很好,扩展性也很好,通过key对数据起到解释说明~

对于xml来说解释说明是用过标签,需要开始和结束两个标签来说,比较占用空间,相比之下,json只使用一个key就能描述,占用的空间比xml少,能节约一点带宽.

缺点:虽然json比xml更节省了带宽,但是很明显,这里的带宽仍然是有浪费的部分~~,尤其是这种数组格式的json.这种情况下,传输的数据字段都是相同的,使刚才这里的key名字被重复传输了.

3.protobuffer协议格式

这是一种更节省带宽的方式,效率最高的方式

  只是开发阶段(代码)定义出这里都有哪些资源,描述每个字段的含义

 程序真正运行的时候,实际传输的数据是不包含这样的描述信息.

这样的数据是按照二进制的方式来进行组织的~~

这样的设定,目前来看是最高效的做法,(程序运行的效率高)不太有利于程序员进行阅读

虽然protobuffer运行效率高,但是使用并没有json更为广泛.

只是哪些对于性能要求非常高的场景,才会去使用protobuffer

传输层:虽然已经在系统内核实现好了,但是也需要重点关注,这里使用的socket api都是传输层提供的.

端口号:端口号是一个2字节的整数,使用端口号的时候,1-1024都是系统保留自用的端口号(知名端口号)-->HTTP服务器80,HTTPS服务器,443

UDP协议~~

无连接,不可靠传输,面向数据报,全双工

我们在研究一个协议时,主要就是研究报文格式,基于报文格式,了解这个协议的其他各个特性

UDP 数据报=报头(重点) +载荷(应用层数据包)

UDP报头中一共有4个字段,每个字段2个字节,(一共8个字节)

由于协议报头中使用2个字节表示端口号,端口号的取值是0-65535,

数据报最大长度的64KB

随着网络的发展,大数据时代的到来,各种格式的数据字段越来越大,有可能在大小上突破64KB

,一旦整个数据报的长度超出64kb,此时就会出现截断(本来数据是完整的,后面的部分没了)

总的UDP数据报最大长度是64kb,载荷部分能承担的最大程度应该是64kb-8

解决这种问题方案

方案一:在应用层,把数据包进行拆分,之前一个数据报表示N个广告(把整个页面的广告包含进去,拆成每个广告占用一个UDP数据报,甚至可以进一步的拆成一个广告对应多个UDP数据报~~

开发成本大,测试成本也很大,容易出问题)

方案二:使用TCP代替UDP~~ TCP没有上述长度的限制~因此问题也就解决了.

校验和/检验和:

验证数据在传输过程中是否正确~~

前提:数据在网络传输过程中,可能会坏掉.

网络数据传输,本质上是光信号/电信号/电磁波(这些信号很有可能会受到干扰)

对于电,磁,电磁波,如果加上一个磁场,很有可能之前的高电平变成了低电平,原来的低电平变成了高电平,此时就出现了0变成1,1变成0,也就是比特翻转的情况.

校验和/检验和的作用就是用来识别当前的数据是否出现了比特翻转~~检验当前的数据是否正确

如果发现是出现了,就可以把这个错误的数据包丢弃掉,避免将错就错

网络中的校验和并非是简单的按照长度/数量作为检验的标准的,一定要让数据的内容能够参与进去.

所谓的校验和,其实就是通过数据中的部分内容,进行一系列的计算,得到了一个更短的字符串,通过原来的数据再计算一次这样的结果,进行对比,看是否一致.

校验和是拿着原始信息的一部分内容去参与计算的,有可能会出现,内容虽然错了,但是算出的校验和还是和之前一致的.(但是这种情况概率比较小,实践中可以忽略不计).

严格的来说,校验和只能用来"证伪",证明数据出错了,无法确保这个数据100%正确.但是实践中可以近似的认为校验和一致,原来的数据就一致.

UDP校验和中:

CRC算法实现:

short checksum=0;

for(遍历取出数据报中的每个字节的数据){

checksum+=当前字节的数据;

}

CRC算法:

UDP数据报发送方,在发送之前,先计算一遍CRC,把计算好的CRC值放到UDP数据报中,(设这个CRC值为value1)

接下来这个数据包通过网络传输到达接收端.接收端接收这个数据之后,也会按照同样的算法,再计算一次CRC的值,得到的结果是value2,比较自己计算的value2和收到的value1是否一致~~如果是一致的,说明数据是ok的,如果不一致,说明传输过程中发生了比特翻转.

在上述CRC算法中,如果只有一个bit发生了翻转,此时能够100%发现问题,可是如果有是两个或多个,可能会和翻转之后计算的一样(这种情况概率很低,可以忽略不计)

md5算法:

1.定长:无论原始数据多长,算出来的md5的最终值都是固定长度,常见的md5版本有16位版本(2字节),32位版本(4字节),64位版本(8字节)

2.分散:计算md5的过程中,原始数据,只要变化一点点,算出来的md5值就会差异很大.

网络传输中,如果出现bit翻转,意味着只是极少的bit翻转了.即使只是翻转一个bit,最终得到的md5值都会差异非常大.这样的特性,也决定了md5也可以作为一个字符串hash算法.

3:不可逆性,给一个源字符串,计算md5值,但是给你一个计算好的md5值,让你把他还原回原始的字符串,理论上是无法完成的,原始的字符串=>md5这个过程中,有很多信息量损失了.直接还原不行.

md5也可以用于加密

理解UDP的不可靠

在面向数据报编程中,应用层交给UDP多长的报文,UDP原样发送,既不会拆分,也不会合并

TCP协议

这里的源端口和目的端口和UDP是一样的,选项及以上都是报头,数据是载荷,

4位首部长度

(报头长度)(header),不像UDP的报,固定是8个字节~~

TCP的前20个字节是固定长度的,后面这路包含了选项(optional)部分

4位首部长度,4个bit位,0-15,此处设定的这里的单位是4字节,而不是字节

1111=>15,在15的基础上就是60字节'

保留(6位) reserved 保留位

UDP这个协议 长度受到2个字节的限制,想要进行扩展,发现扩展不了.一旦你改变了这里的报头长度,就会使机器发送的UDP数据报和其他机器不兼容,无法通信了.

因此,我们的TCP在设定报头的时候,就提前准备了几个保留位,(虽然现在不用,但也是先占个位置),后面一旦需要用了,咱们就可以把这些保留位给使用起来.后续一旦需要扩展功能,使用保留位就可以实现,就可以避免tcp的扩展引起不兼容的问题.

 6位标志位,TCP最核心的部分

16位校验和,类似于UDP的校验和.把报头和数据载荷放到一起计算校验和

TCP内部的机制是很多的.上述报头字段都是针对TCP的各个机制的支撑属性.

需要了解TCP的其他机制,才能认识报头的含义.

TCP特点:有连接,可靠传输,面向字节流,全双工.

可靠传输:TCP安身立命之本,初心是解决"可靠传输"问题.

网络通信过程是复杂的,无法确保发送方发出去的数据,100%能够达到接收方

此处的可靠性是退而求其次,只要尽可能的去进行发送了,发送方能够知道对方是否收到,就认为是可靠传输了.

1.用来确保可靠性,最核心的机制,成为"确认应答"

    第一种时序有些过于理想化了,但是实际情况会经常出现"后发先至"情况,如果出现了后发先至情况,那么理解起来就有问题了

后发先至:

一个数据包从发送方到接收方传输过程中走的路径可能不一样,第一个数据包走路劲一,第二个数据包走路径了,与可能路径二非常畅通,路线一堵车了,第二个数据包虽然发的言辞,但是能先到.

为了解决上述问题,引入了序号和确认序号,对数据进行编号.应答报文里就告诉对方,我这次应答的是哪个数据.

这是简化版本的模型,真实TCP的情况要更为复杂一些,TCP四面向字节流的,以字节为单位进行传输的,没有"一条两条"概念,

实际上,TCP的序号和确认序号都是以字节来进行编号的.

在合理我们假设载荷有1000个字节,有1000个序号~~,由于序号是连续的.只需要在报头中保存第一个字节的序号,即可后续字节的序号都是很容易就计算到的.

应答报文中的确认序号,是按照发送过去的最后一个字节的序号加1进行设定的

主机B收到了1-1000这些字节数据之后,反馈一个应答报文.应答报文中的确认信号的值就是1001

1001的含义:

1.<1001的数据,都已经收到了

2.发送方接下来要给我发1001开始的数据了

TCP的确认应答是确保TCP可靠性的最核心的机制

确认应答中,通过应答报文来反馈给发送方,表示当前的数据正确收到了

应答报文,也叫ack报文.

平时ACK位为0,如果当前报文为应答报文的话,ACK位为1.

在接收的时候,我们希望应用程序读到的数据是顺序正确的~~顺序不对,对于接收应用程序的逻辑肯定也会有一定的影响~~

接收缓冲区可以认为是一个"优先级队列"以序号作为优先级的参考依据

2.超时重传.是确认应答的补充

如果一切顺利,通过应答报文就可以告诉发送方,当前数据是不是成功收到.

但是,网络上可能存在"丢包"情况,如果数据包丢了,没有到达对方,对方自然就没有ack报文了.

这个情况下,就需要超时重传了.

TCP可靠性就是在对抗丢包~~期望在丢包客观存在的情况下,也能够尽可能的把包给传过去.

发送方发了数据之后要等.等待的时间里:收到了ack(数据报在网络上传输,需要时间的)

如果等了好久,ack还没等到,此时发送方就认为数据的传输出现丢包了.

当认为丢包之后,就会把刚才的数据包再传输一次.(重传)

等待的过程有一个时间的阈值(上限),就是超时

丢包:

这个网络中的路由器/交换机,不仅仅是给你这一次通信提供服务,还要能支持千千万万的主机之间的通信

整个网络,就可能存在某个交换机/路由器,某个时刻,突然负载量很高,短时间内可能有大量的数据包要经过这个设备转发.

但是要知道,一台设备能够处理的数据量是有限的!很可能瞬间的高负载超出了这个设备能转发的数据量的极限,此时多出来的部分就无了~就被设备丢包了

在传输过程中,碰巧某个数据包遇见了上述情况,就会丢包

上面的过程中,是认为没收到ack就是丢包,

但是,丢包并不一定是数据丢了,也有可能是ack丢了

数据丢了还是ack丢了,在发送方角度看起来,就是区分不了,都是ack没收到~~

正常情况下的丢包,主机A发送的数据没有到达主机B

如果主机A在特定的时间间隔内没有收到主机B的ack应答,就会把数据再发送一次

这种情况下,数据已经被B收到了,再传输一次,同一份数据,B就会收到两次.

TCP socket在内核中存在接收缓冲区(一块内存空间)

发送方发来的数据,是要先放到接收缓冲区中的.这里应用程序调用read/scanner.next才能读到数据.这里的读操作其实就是读接收缓冲区

接收缓冲区,除了能够帮助我们进行去重之外,还能够进行排序.对收到的数据进行排序,按照序号来排序,确保应用程序读到的数据和发送的数据顺序是一致的.

当数据到达接收缓冲区的时候,接收方会首先判定一下当前缓冲区中是否已经有这个数据了(或者这个数据曾经在缓冲区存在过)

如果已经存在或者存在过,就直接把重复发来的数据就丢弃掉了~~

就能确保应用程序在调用read/scanner.next的时候,不会出现重复数据了.

接收方判定数据是"重复数据"的核心依据:

1.数据还在接收缓冲区,还没被read走,此时,就拿着新收到的数据,和缓冲区中的所有数据的序号对一下,看看有没有一样的.有一样就是重复了,就可以把新收到的数据丢弃了

2.数据在接收缓冲区中,已经被应用程序给read走了,此时新来的数据序号是无法直接在接收缓冲区中查到的.注意!!应用程序读取数据的时候,是按照序号的先后顺序,连续读取的!

一定是先读序号小的数据,然后再读序号大的数据(可以把接收缓冲区当作一个带有优先级的阻塞队列)

此时socket api上就可以记录上次读的最后一个字节的序号是多少~~

比如上次的的最后一个字节的序号是3000新收到一个数据包的序号是1001,这个1001一定是之前已经度过的了,这个时候同样可以把这个新的数据包判定为"重复的包",直接丢弃掉了.

上述谈到的,ack重传,保证顺序,自动去重,都是TCP内置的.咱们使用TCP的api的时候

outputStream.write()只需要调用一个简单的代码,上述功能就自动生效了,如果使用UDP,上述这些问题就得好好考虑考虑.

超时是会重传,但也不是无限的重传....

1.重传次数是有上限的.重传到一定程度还没有ack,就尝试重置连接,如果重置也失败,就直接放弃连接.

2.重传的超时时间阈值也不是固定不变的,随着重传次数的增加而增大(重传频率越来越低),经历了重传之后还丢包,大概率是网络问题.

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Vue3 (unplugin-auto-import自动导入的使用)

安装 参考链接 npm i -D unplugin-auto-importvite.config.ts里面配置 import AutoImport from unplugin-auto-import/viteAutoImport({imports:[ vue,vue-router]})重新运行项目会生成一个auto-imports.d.ts的文件 /* eslint-disable */ /* prettier-ignore */ // ts-nochec…

C++之类作用域

目录 1、全局作用域 2、类作用域 2.1、设计模式之Pimpl 2.2、单例模式的自动释放 2.2.0、检测内存泄漏的工具valgrind 2.2.1、可以使用友元形式进行设计 2.2.2、内部类加静态数据成员形式 2.2.3、atexit方式进行 2.2.4、pthread_once形式 作用域可以分为类作用域、类名…

高并发系统实战课个人总结(极客时间)

高并发系统实战课 场景 读多写少 我会以占比最高的“读多写少”系统带你入门&#xff0c;梳理和改造用户中心项目。这类系统的优化工作会聚焦于如何通过缓存分担数据库查询压力&#xff0c;所以我们的学习重点就是做好缓存&#xff0c;包括但不限于数据梳理、做数据缓存、加缓…

有趣的CSS - 文字加载动画效果

大家好&#xff0c;我是 Just&#xff0c;这里是「设计师工作日常」&#xff0c;今天分享的是用 css 实现多字符模拟加载动画效果。 《有趣的css》系列最新实例通过公众号「设计师工作日常」发布。 目录 整体效果核心代码html 代码css 部分代码 完整代码如下html 页面css 样式页…

【Python笔记-设计模式】享元模式

一、说明 享元模式是一种结构型设计模式&#xff0c;它摒弃了在每个对象中保存所有数据的方式&#xff0c;通过共享多个对象所共有的相同状态&#xff0c;让你能在有限的内存容量中载入更多对象。 (一) 解决问题 旨在减少大量相似对象创建时的内存开销 (二) 使用场景 大量…

这是我见过最全的权限系统设计方案!

日常工作中权限的问题时时刻刻伴随着我们&#xff0c;程序员新入职一家公司需要找人开通各种权限&#xff0c;比如网络连接的权限、编码下载提交的权限、监控平台登录的权限、运营平台查数据的权限等等。 在很多时候我们会觉得这么多繁杂的申请给工作带来不便&#xff0c;并且…

[更新]ARCGIS之土地耕地占补平衡、进出平衡系统报备坐标txt格式批量导出工具(定制开发版)

序言 之前开发的耕地占补平衡报备格式&#xff0c;现在之前的基础上集成了耕地进出平衡报备格式导出。 之前版本软件详见&#xff1a;软件介绍 一、软件简介 本软件是基于arcgis二次开发的工具&#xff08;插件&#xff09;&#xff0c;需要授权后才能使用&#xff1b; 本软件…

125 Linux C++ 系统编程4 Linux 静态库制作,动态库制作,静态库和动态库对比。静态库运行时找不到库的bug fix

一 静态库 和动态库 对比 静态库的原理&#xff1a;假设我们有一个 静态库&#xff0c;大小为500M&#xff0c;这个静态库实现了一些打牌的逻辑算法&#xff0c;提供了一堆API&#xff0c;让开发者 可以轻松的实现 54张扑克牌的随机发牌&#xff0c;指定发牌等功能。 我们写了…

Nuxt3实现多语言与事件总线(EventBus)

我的nuxt版本为 3.10.0 一、多语言实现 这里我使用得是 nuxtjs/i18n 这个库 安装 npm install -D nuxtjs/i18nnext根目录创建 i18n.config.ts 文件 export default {legacy: false,locale: zh, // 默认值messages: {zh: {home: 首页,useKill: 使用技巧,helpCenter: 帮助中…

H桥逆变控制方式(单极性倍频)

单极性倍频图像 内部做了载波取反&#xff1a;正相载波和负相载波 最后都和调制载波一起比较 正相载波&#xff1a;Q7导通为高电平&#xff0c;Q15导通为低电平 负相载波&#xff1a;Q16导通为高电平&#xff0c;Q8导通为低电平 导通次序为&#xff1a;Q7Q16——Q7Q8——Q7Q…

Mamba 作者谈 LLM 未来架构

文章目录 前言 1、为什么注意力机制有效&#xff1f; 2、注意力计算量呈平方级增长 3、Striped Hyena 是个什么模型&#xff1f; 4、什么是 Mamba? 5、Mamba 硬件优化 6、2024年架构预测 7、对 AI 更多的预测 本片文章来自【机器之心】对Mamba作者进行采访所进行的编译整理。 …

Sora 对未来视频创作伦理的挑战和思考

Sora 对未来视频创作伦理的挑战和思考 随着人工智能技术的飞速发展&#xff0c;AI视频模型Sora的出现为视频创作带来了革命性的变革。然而&#xff0c;在技术进步的同时&#xff0c;也带来了一些伦理问题值得我们深思。 1. 真实性和虚假信息: Sora能够生成逼真的视频画面&…

初识51单片机

##江科大51单片机学习 什么是单片机&#xff1f;&#xff1f;&#xff1f; 单片机&#xff0c;英文名&#xff0c;Micro Controller Unit&#xff0c;简称MCU&#xff08;tips&#xff1a;有人会简称它为CPU&#xff0c;但不是如此&#xff0c;CPU其实被集成在MCU中&#xff…

人工智能 — 数字图像

目录 一、图像1、像素2、图像分辨率3、RGB 模型4、灰度5、通道6、对比度7、RGB 转化为 Gray8、RGB 值转化为浮点数9、二值化10、常用视觉库11、频率12、幅值 二、图像的取样与量化1、数字图像2、取样3、量化 三、上采样与下采样1、上采样&#xff08;upsampling&#xff09;2、…

测试计划、测试方案、测试策略、测试用例的区别

一 测试计划 测试计划是指描述了要进行的测试活动的范围、方法、资源和进度的文档。它主要包括测试项、被测特性、各阶段的测试任务、时间进度安排&#xff0c;谁执行任务和风险控制等&#xff0c;可以包括测试策略。 二 测试方案 测试方案是指描述需要测试的特性、测试的方…

jvm-jvm七款经典垃圾收集器

一&#xff0c;七款经典垃圾收集器 七款经典的垃圾收集器&#xff1a; 收集器串行、并行or并发新生代/老年代算法目标适用场景Serial串行新生代复制算法响应速度优先单CPU环境下的Client模式Serial Old串行老年代标记-整理响应速度优先单CPU环境下的Client模式、CMS的后备预案…

基于Java SSM框架实现艺诚美业管理系统项目【项目源码+论文说明】计算机毕业设计

基于java的SSM框架实现艺诚美业管理系统演示 摘要 21世纪的今天&#xff0c;随着社会的不断发展与进步&#xff0c;人们对于信息科学化的认识&#xff0c;已由低层次向高层次发展&#xff0c;由原来的感性认识向理性认识提高&#xff0c;管理工作的重要性已逐渐被人们所认识&a…

SpringBoot实现缓存预热的几种常用方案

&#x1f3f7;️个人主页&#xff1a;牵着猫散步的鼠鼠 &#x1f3f7;️系列专栏&#xff1a;Java全栈-专栏 &#x1f3f7;️个人学习笔记&#xff0c;若有缺误&#xff0c;欢迎评论区指正 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&…

visual studio2019怎么修改字体

点击菜单栏中的“工具” “选项” 环境 -> 字体和颜色 Consolas是vscode的默认字体&#xff0c;还挺好用的。

【自然语言处理-二-attention注意力 是什么】

自然语言处理二-attention 注意力机制 自然语言处理二-attention 注意力记忆能力回顾下RNN&#xff08;也包括LSTM GRU&#xff09;解决memory问题改进后基于attention注意力的modelmatch操作softmax操作softmax值与hidder layer的值做weight sum 计算和将计算出来的和作为memo…