《JavaEE》网络编程TCP/IP五层协议万字详解

news2024/11/17 7:28:05

文章目录

  • TCP/IP五层协议栈
    • 应用层
      • xml (可读性比较好 但是运行效率不高)
      • json(可读性好 但是运行效率不高)
      • prtobuffer(可读性不好 但是运行效率很高)
  • 传输层
    • UDP
  • TCP
    • TCP数据解读
      • 32位序号
      • 32位确认序号
      • 4位首部的长度
      • 保留位
      • 6位标志位字段
      • 16位窗口大小
      • 16位校验和
      • 16位紧急指针
      • 选项
    • 确认应答(保证可靠传输的核心机制)
    • 超时重传(相当于对确认应答做了补充)
    • 连接管理(TCP保证可靠性的机制)
      • 建立连接 三次握手
      • 如何断开连接(四次挥手)
    • 滑动窗口
    • 流量控制
    • 拥塞控制
    • 延时应答
    • 捎带应答
    • 面向字节流
    • 异常处理
  • 网络层
    • IP协议
  • 数据链路层
  • 物理层


👑作者主页:Java冰激凌
📖专栏链接:JavaEE


TCP/IP五层协议栈

应用层

在应用层中 最重要的就是数据要在网络中进行传输 所以说 在应用层中最主要的是要约定一个“应用层协议”在约定协议的时候 主要包含两个工作

  • 明确传输的信息
  • 明确数据的组织格式

当然因为应用层使用的广泛 业界也有不少的优秀的协议模板 我们大概来看一下

xml (可读性比较好 但是运行效率不高)

他采用的数据组织格式使用了标签 有点类似于HTML的语法 我们来简单的看一下在这里插入图片描述
数据组织格式大概如下 其中 标签名表示的就是Key 数据表示的就是Value 也是Key-Value结构的

在这里插入图片描述


json(可读性好 但是运行效率不高)

json是当下最流行使用的数据组织格式 他也是采用Key-Value的结构的 但是相比较于xml来说还是更加高效的 他的结构是这样的:

  • 通过{}构成了键值对结构
  • 一个{}中有很多个键值对
  • 键值对之间使用逗号分割
  • 键和值之间使用冒号分割
  • 要求键必须是字符串类型的
  • 值运行很多类似(数字 字符串 布尔 数字 甚至是另一个json)
    在这里插入图片描述
    json中表示字符串 单引号和双引号都可以 最后一个键值对后面可以有逗号 也可以没有
    json要求key一定是字符串 因此 key这里的引号可以省略 除非key中包含了一些特殊符号 (比如想空格 或者-…) 必须要加上引号

prtobuffer(可读性不好 但是运行效率很高)

prtobuffer是一种二进制格式的数据 同时再通过一个IDL文件来描述这个数据格式 IDL只是起到了一个辅助开发的效果 并不会真正传输 传输的只是二进制的数据
在这里插入图片描述
虽然我们编写的是文本 但是传输的时候会被压缩为二进制的 甚至会重新进行编排


设计应用层协议 是一件普通的事情
设计应用层协议 要做的工作

  • 明确传输的信息(根据需求)
  • 明确传输的格式(参考现有的模板 xml json protobuffer)
    当然 http 也是业界优秀的协议

传输层

我们之前已经提到过 端口号是有0-65535 但是其中也有一些知名的端口号 就例如0-1024被专门划分出来固定分配个对应的应用 其中 传输层最常见的协议 :TCP 和 UDP 我们来详细了解一下

UDP

我们上一篇文章已经介绍了UDP的基本特点:无连接 不可靠传输 面向数据报 全双工
忘记的或者不知道的可以点击下面蓝色字体跳转
网络编程套接字
在这里插入图片描述
其中 源端口号就是代表发送数据的端口 目的端口代表数据要发送给哪个端口 长度代表这个数据报的长度 校验和我们来着重的介绍一下
校验和类似于我们的长度校验 首部校验 我们的校验和中存储的可能是一个数字 这个数字可能是代表传输的数据的个数 也可以是根据数据内容计算出来的校验和 如果数据出错 那么根据校验和 我们就可以明确的知道 这个包当前的数据时错误的 我们都知道孔子的论语的命名 都是取的文首句的二三字 就是类似的原理

其中还有提到的是 因为UDP是发送的数据报 所以说UDP的数据每次发送的是有上限的 那么对于一个很大的数据如果使用UDP传输该如何传输呢?此时可以在应用层 针对较大的数据报来进行分包 然后通过多个UDP来进行传输 这个时候接收方再通过收到的多个包来进行拼接成完整的数据 但是这个并不是一个好的方法 因为我们要考虑到的东西会很多 例如我们数据拆包之后 发送到接收方的时候接收方如何进行组包 还要考虑 如果发生了丢包该怎么办 (因为UDP是不可靠传输)那么此时 最好的解决策略就是使用TCP 对于TCP是面向字节流的 是没有长度大小的限制的


TCP

TCP是一块难啃的骨头 但是全程无尿点 TCP的各种机制精妙绝伦
在这里插入图片描述

TCP数据解读

我们先来简单的介绍一下TCP的数据报格式
首先和我们的UDP一样 都拥有这源端口号、目的端口号

32位序号

每个TCP报文段都包含一个序号字段用于标识该报文段所携带的数据块在整个数据流中的位置 发送 方在发送数据时 会给每个数据块分配一个唯一的序号 接收方在接收数据时 会根据序号来识别数据块的顺序以及是否有数据丢失或重复

32位确认序号

接收方在接收到数据后 需要向发送方发送一个确认报文段其中包含一个确认序号字段 用于回应发送方已经成功接收到的数据的最高序号(即已经被正确接收的数据的下一个字节序号 )发送方在收到确认报文段后 就可以知道接收方已经成功接收到了哪些数据 可以继续发送下一批数据块

4位首部的长度

4个bit位 可以表示0-15 表示TCP报头的长度 此处的单位是4字节 例如1111 代表 15 * 4 = 60字节

保留位

暂时未启动 为了以后升级预留的空间

6位标志位字段

这个字段中的每一个代表着不同的功能
这6个标志位分别是:URG、ACK、PSH、RST、SYN和FIN

  • URG(紧急位):用于指示当前报文段中是否包含紧急数据。如果这个标志被设置为1,那么表明当前报文段中包含了紧急数据,需要发送方和接收方进行特殊处理
  • ACK(确认位):用于确认收到的数据。如果这个标志被设置为1,那么表明当前报文段是一个确认报文段,用于确认前面发送的数据已经被正确地接收到了
  • PSH(推送位):用于通知接收方应该立即将报文段中的数据推送给应用程序而不是等待缓存填满。如果这个标志被设置为1,那么表明发送方要求接收方应该受理当前数据段而不需要等待缓存区填满
  • SYN(同步位):用于建立连接。如果这个标志被设置为1,那么表明当前报文段用于建立连接,请求对方回复一个ACK报文段以确认连接
  • FIN(结束位):用于结束连接。如果这个标志被设置为1,那么表明当前报文段用于结束连接,请求对方回复一个ACK报文段以确认连接断开

16位窗口大小

接收方可以接收而不会拥塞的字节数的最大值

16位校验和

类似于UDP的检验和

16位紧急指针

用于指示报文段中的紧急数据的位置,也就是报文段中紧急数据的起始偏移量。当URG标志被设置为1时,紧急指针就变得有意义了 如果没有紧急数据的话 这个紧急指针也可以不存在 一般用于一个需要快速响应的操作 例如cmd窗口中输入了ctrl+c 强制停止 就需要立即处理停止操作

选项

这个选项是可以有一个 也可以有多个 当然也可以是没有的


确认应答(保证可靠传输的核心机制)

关键就是在给接收方发送消息后 接收方会返回一个应答报文ACK表示接收方已经收到了
确认序号就类似于我们平时的聊天 可能一次发送一个消息 对方回复收到 代表对方已经收到了 如果其中发生了丢包事件 那么不管是哪边丢失 都能保证消息的送达 例如假设我们的发送方要发送的消息丢包了 隔了一段时间没有收到接收方发回的ACK 那么我们就认为是丢包了 就会给接收方重发消息 那么接收方发送的ACK丢了怎么办呢? 还是一样的道理 当发送方发送数据后 没有收到接收方发回的ACK 就认为是丢包了 会出发超时重传(稍等就会介绍到)重新发送消息给接收方 接收方收到一看 这不是刚刚发过的数据吗 那么接收方就明确知道自己发送的ACK丢了 就会重新发送ACK给发送方
我们来简单画一个序号和确认序号对应到TCP模型中
在这里插入图片描述


超时重传(相当于对确认应答做了补充)

如果出现了丢包 那么我们的超时重传机制就要启动了
还是我们刚刚的举例 假设我们还是主机A和主机B
在这里插入图片描述
好 我们再来看一些确认应答ACK丢失
在这里插入图片描述
重传的这个时间频率也不是固定的 一般来说会逐渐变大 重传的频率会逐渐降低 如果发送两次 丢包概率会大大降低 假设发送失败的概率是10% 失败两次的概率假设1% 三次的概率假设0.1% 多次重传 概率会大大降低 (在保持网络正常的情况下)但是如果出现了连续10次 或者100次 就认为这个连接已经断开了 相信大家都不免遇到网络不好一直在断线重连吧
在这里插入图片描述

但是如果是ACK丢了 触发了超时重传 这个时候会导致出现接收方收到了重复的消息 其他的消息问题不大 但是涉及到钱就不一样了 所以 在TCP的内部会有一个去重的操作 接收方收到的数据会先放到操作系统内核的"接收缓存区"中 (是一个内存空间 也可以认为是一个阻塞队列)每当收到了新的数据 TCP就会根据序号 来检查这个数据是不是在接收缓冲区中已经存在了 如果不存在就放进去 如果存在 就直接丢弃这样的操作保证了应用程序中调用socket api拿到的这个数据一定是不重复的
重传如果失败 可能还会尝试 也不会无休止的重传 如果连续几次都不行 那么就认为这个网络可能是遇到了严重的情况 (自动的断开TCP的连接)


连接管理(TCP保证可靠性的机制)

TCP的状态 (两种常见的状态)
LISTEN 表示服务器启动成功 端口绑定成功 随时可以有客户端来建立连接
ESTABLISHED 表示客户端已经连接成功 随时可以进行通信了
以下是一个经典面试题 TCP的三次握手四次挥手


建立连接 三次握手

客户端和服务器经过三次交互完成了建立的过程
客户端是主动发起请求的一方 所以会从客户端先开始向服务器端发送一个SYN同步报文段 服务器收到的话 会返回一个ACK报文段 并且也会发送一次SYN报文段 而且这两个报文段大概率是会合二为一的 因为封装两个报文段肯定没有一次来的高效 之后客户端收到之后会返回一个ACK作为应答
在这里插入图片描述
三次握手有啥用?和可靠性有啥关系?
三次握手相当于是在投石问路 主要就是为了确认客户端服务器双方的接收和发送功能是否正常
举个栗子 : 就像我们打电话的时候 首先
我: 喂 能听到吗? (此时当对方听到我说话对方就明确了我的发送能力是没问题的)
对方:可以听到! 你能听到我说话吗?(此时当我收到这个消息之后我就明确 我的发送能力和对方的接收能力与发送能力都是没问题的 但是当前对方还不知道对方的发送功能是否正常 于是我再告诉他)
我:可以的可以的(此时双方都明确了双方的接收和发送能力都是完整的)

经历了三次握手 通信双方都验证了各自的发送能力和接收能力都可以 接下来就可以继续进行可靠传输了当然 三次握手不单单交互的是这些 还会协商一些具体参数 就像我们打电话的时候 问问对方吃饭了没 在哪里了这些


如何断开连接(四次挥手)

四次挥手 双方各自向对方发送了FIN(结束报文段) 请求 并且各自给对方一个ACK确认报文
三次挥手 一定是客户端主动发起的主动发起的一方才叫客户端
四次挥手 可能是客户端发起的 也可能是服务器主动发起的
三次挥手 中间两次是可以合并的
四次挥手 中间两次有时候合并不了 有时候可以合并
假设 我们客户端要跟服务器断开连接
首先我们的客户端会给服务器发送一个YIN报文段表示要断开连接
服务器收到之后会立即返回一个ACK报文段
之后服务器还会返回一个YIN报文段
(为何这两次不会合并 这两次是大概率不会合并的 因为ACK的返回是内核态处理的 而YIN是代码负责的)
之后客户端会返回一个ACK 此时连接断开
不能合并的原因?
在于B发送ACK和B发送FIN的时机是不同的 在四次挥手中 B给A发的ACK是内核负责的 B给A发送的FIN是用户代码负责的 只有在代码中调用了socket.close()才会发送(FIN)如果这两个操作之间的时间差比较大 就不能合并了 如果时间差比较小 可能会合并的(延时应答和捎带应答)
在这里插入图片描述
其中需要注意到的是 当客户端发送FIN报文段之后 会等待服务器的ACK 收到ACK之后 客户端不会立马断开连接 会等待服务器的FIN请求 之后再给服务器返回一个ACK报文段 那么发送报文段之后就会断开吗 nonono 还是不会立即断开 因为如果客户端发送的ACK丢失之后 那么服务器没有收到ACK 就会触发超时重传机制 如果此时释放之后就会收不到请求 所以 其实断开之后 客户端和服务器的连接还会存在一定的时候
我们举个栗子 A为客户端 B为服务器 假设A和B是一对恋人 今天他们吵架了 要分手了
A:分手吧(FIN)(此时发送FIN请求 如果没有收到B的回应 就会认为是他没有听到 会重新说 分手)
B:啊?(ACK)(此时发送ACK请求 表示已经收到了消息)
B:(经过考虑)好!分手吧(FIN)(此时经过思考 也就是过了一段时间后 就会发送FIN)
A:行 分手就分手!(ACK)(此时A已经名义上和B分手了)
(但是A和B的连接不会马上断开 因为要分开 但是彼此的东西太多了 要经过一段时间的才能彻底断开 然后经过一段时间才会忘掉 断开连接后还要存在一定的时间)


TCP/IP 模型中哪一层处理传输的可靠性、流量控制和错误控制(传输层)


在这里插入图片描述
此外 我们还要认识两个状态
CLOSE_WAIT 四次挥手挥了两次之后出现的状态 这个状态就是在等待代码中调用socket.close() 方法 来进行后续的过程 (ps:正常情况下 一个服务器上不应该存在大量的CLOSE_WAIT 如果存在 说明大概率是代码bug 导致close没有被执行到)
TIME_WAIT 谁主动发起FIN 谁就进入TIME_WAIT 起的效果就是给最后一次ACK提供重传的机会(因为在A发送完ACK之后 可能会出现ACK丢包的情况 如果出现最后一个ACK丢包了 那么B在一段时间没有接收到ACK 可能会认为是FIN丢包了 会进行重传(超时重传) 那么如果现在A已被释放了 那么B这个资源就无法被释放 导致的可能会在服务器淤积过多的数据)因此 要进入TIME_WAIT状态 不要释放的太早 要等待一段时间 确保B不会再重传FIN 之后 再去销毁
即使TCP做了很多工作来保证可靠 但是TCP也在很怒力的提高传输速度


滑动窗口

滑动窗口所存在的意义 就是在保证可靠性的前提下 尽可能的提高传输的速度 如果一次发送的数量为一 那么我们每一次发送后都需要等待服务器的ACK 如此一来会浪费大量的等待时间 这明显不是我们想看到的 所以在这个基础上 滑动窗口就是为了解决这个问题来的

滑动窗口的工作原理是什么呢?
如果一次批量发送的数据为N 统一等待一波 此时这里N成为窗口大小
“滑动”的意思是 并不用把N组数据的ACK都等到了 才继续往下发送 而是收到一个ACK 就继续往下发一组

我们来看一个图
在这里插入图片描述
我们这样做的好处是 不需要一直等待1001、2001、3001、4001响应 当前我们同时等待的是四组ACK 只要1001到了 就可以往下多发一组(4001 - 5000)此时我们等待ACK的范围就改变了 (2001 - 5001) 一份等待的时间 等待了多组ACK 就把等待多份ACK的时间压缩成一份了

那么我们就诞生出了新的问题 我们不等这个ACK直接发送不行吗?

等 必须等 TCP是可靠传输 可靠传输的一个组成必要就是确认应答

如果传输中提前到达了2001 1001还未收到呢?

出现这个情况是很正常的 首先我们要明确 在网络中传输有快有慢 有的选择了最优路径 有的选择了最差路径 所以会导致ACK的到达有快有慢 但是 当我们收到2001ACK/的时候 我们此时认为 从2001之前的数据已经全都被服务器接收到了 为何是这样呢 因为服务器的确认序号是根据序号来进行返回的 而且这个序号只增不减 当我们收到2001 的ACK的时候 就证明服务器已经收到了2001前的所有数据 所以此时我们并不需要关注1001的ACK是否丢包或者未到达 直接滑动窗口即可
在这里插入图片描述
并且 这个窗口大小越大 我们可以认为传输速度越快


我们加入滑档窗口之后会有一个核心问题 丢包 !

因为我们发送的是多组的数据 当我们进行大批量发送的时候 当网络不稳定的时候 这个时候出现丢包的概率就变得很大
ACK丢了

在这里插入图片描述
这个是我们构造出的丢包的情况 我们其中 1001、3001、4001的ACK都发生了丢失 但是我们是正常收到了2001、5001、6001 其实当我们收到2001的ACK的时候 就可以证明1001的ACK已经被服务器发送 也就代表着服务器已经收到1-1000的数据 所以 1001的ACK是否收到 已经变的不重要了ACK确认序号的特地含义就保证了后一条ACK能够涵盖前一条

这个我们也来举个栗子~
这个就好比找对象
首先我们认为谈恋爱有以下步骤

  • 拉小手
  • 抱抱
  • 么么哒
  • ……(以下内容付费观看)
    这几个步骤中 后者肯定是涵盖前者的 当你们可以么么哒的时候 肯定拉小手 抱抱是肯定允许的

ACK也像是在升级 当你已经10级的时候 你肯定已经经历过5级、6级


数据丢了
在这里插入图片描述
如上图所示 当我们的1001-2000数据丢失的时候 服务器端会多次返回1001的ACK 代表1001之后的数据有丢包 没有收到 此时客户端会重复发送1001-2000 当服务器收到之后会继续返回7001的ACK
在这里插入图片描述


流量控制

流量控制是滑动窗口的延伸 目的是为了保证可靠性的同时尽可能提升传输效率

我们知道 在滑动窗口中 窗口越大 传输速度越快 但是我们在滑动窗口中 只考虑到了客户端 没有考虑到服务器 当发送方发的贼快的时候 但是接收方处理不过来 此时接收方就会直接把新收到的包给丢弃 之后发送方仍旧需要进行重传

流量控制的关键 就是能够衡量接收方的处理速度 此时直接使用接收方接收缓存区中剩余的大小来作为传输的效率

这个也有一点类似我们之前的生产者消费者模型 发送方就是生产者 接收方就是消费者 而接收方的接收缓存区就是交易场所

如果剩余空间比较大 就认为B的处理能力是比较强的 就可以发快点 反之慢点
通过ACK来返回剩余空间 通过TCP中的16位窗口大小来衡量当前接收方剩余的大小
在这里插入图片描述
其中有趣的是 当返回的窗口大小为0的时候 A会停止发送数据 但又不是完全不发 会定期的给客户端发送一个探测报文 这个探测报文不会发送任何数据 只是为了出发ACK 触发了ACK就可以知道当前的窗口大小是多少
在这里插入图片描述


拥塞控制

也是滑动窗口的延伸 也是限制滑动窗口发送的速率

拥塞控制衡量的是 发送方到接收方 这些链路之间 拥堵情况(处理能力)

A能够发多块 不光取决于B的处理能力 也取决于中间链路的处理能力

通过实验的方式 逐渐调整发送速度 找到一个比较合适的范围

发送方刚开始只会以一个比较小的数据包开始发送 如果数据包很流畅的到达了 就开始逐渐加大窗口大小 如果加大到一定的程度之后 出现 了丢包 那么发送方会急速缩小窗口大小 通过反复的增大和缩小 逐渐会找到一个合适的范围 拥塞窗口就会在这个界值中不断的变化
在这里插入图片描述
当他开始缩小的时候 会以指数级别的上升到刚刚的一半界值 然后再缓慢提升

我们还是来举一个例子

这个就好比找对象的感情

刚开始谈恋爱的时候 爱情是非常的甜蜜的 关系飞速上升 但是过一段时间之后 这个新鲜感已经过去了 然后吵架了 感觉就会掉落谷低 之后男生再哄一哄女生 又和好了 关系迅速升温到之间的一半 肯定不会有刚开始的甜蜜期亲密了 如此反复 经过很久之后就会趋于一个稳定的范围


延时应答

相当于流量控制的延伸 流量控制好比踩了一下刹车 使发送方不要发送的太快 延时应答就是在这个基础上 想要尽量的再多发送一些数据
就当发送端向接收端获取剩余空间的时候 接收端暂时不回答 而且尽量多处理一些数据 就可以让发送端多发送一些数据


捎带应答

其实三次握手就有使用到这个捎带应答
捎带应答就是准备好数据后 稍微等一等 如果有其他的数据要发送给接收端 就带上一起发送 这个很好理解


客户端和服务器之间的通信

  • 一问一答 客户端发送一个请求 服务器返回一个对应的请求(浏览器)
  • 多问一答 上传文件
  • 一问多答 下载文件
  • 多问多答 直播、串流

面向字节流

因为TCP是面向字节流的 所以不可避免的会存在粘包问题 (不仅仅是TCP存在粘包问题 其他面向字节流的机制也存在 比如读文件)
那么什么是粘包问题呢?
在这里插入图片描述
假设我们当前A向B发送了3个TCP数据报 这些数据到达B之后 会进行分用 意味着把TCP进行解析了 取出了其中的应用层数据 放到接收缓冲区中
在这里插入图片描述
B的应用程序需要通过read的方式来读取接收缓存区中的数据 因为TCP是面向字节的 那么我们如何得知 从哪里到哪里就是一个完整的数据报呢? 如果没有一个额外的限制 其实就很难进行区分了
原因
TCP的报头是没有长度的
当前接收缓存区 可以视为分用后的数据 此时缓存区中是不带TCP的数据报头的
解决方案
关键就是也要在应用层协议这里加入包的边界
可以约定好在每个包以分号结尾在接收缓存区中以分号来进行切分即可


异常处理

  1. 进程终止
    在进程毫无防备的情况下突然结束这个进程

TCP连接是通过socket来建立的 socket本质上是进程打开的一个文件 文件其实就存在于进程的PCB 里面有一共文件描述符表 每次打开一个文件 (包括sicket)都在文件描述符表中增加一项每次关闭一个文件 都在文件描述符表中删除一项如果直接杀死进程 PCB也就没了 文件描述符表也就没了 此时的文件相当于是自动关闭 这个过程其实和socket.close()一样 都会触发四次挥手

  1. 机器关机

这个很理解 按照正常的流程关机 会让操作系统去杀死所有的进程 然后进行关机 这个流程也会正常的出发四次挥手

  1. 机器掉电、网线断开

这个出现在台式机上比较常见 笔记本一般不会出现这个情况 因为笔记本都有内置电池 直接断开电源 操作系统不会有任何的反应时间 更不会有任何 的处理措施

  • B断电
    在这里插入图片描述
    如果B断电 意味着A发送的所有数据都不会再有ACK了 当A长时间收不到ACK 就会一直进行重传 重传几次后 A就会认为这个连接已经出现 严重的故障 就会主动放弃连接
  • A断电

如果A断电 B就不知道当前是A挂了 还是A休息会儿再使用 因为B是服务器 B就会时不时的给A发送一个探测报文(心跳包)这个心跳包不带有任何数据 只是为了出发ACK 也就是看A服务器是否存活 如果收不到ACK 就认为出现了严重故障 B就会主动断开连接


TCP的特性介绍就撒花啦


总结一些面试题
TCP和UDP对比
啥时候使用TCP?

对可靠性有一定要求

啥时候使用UDP?

对可靠性要求不高 对效率要求更高

如何基于UDP实现可靠传输
本质上就算是再考TCP 只需要在应用层引入TCP的确认应答和超时重传机制即可

传输层的协议 只有TCP和UDP吗?
不是 在达能下常见的对抗性很高的游戏 使用的既不是TCP 也不是UDP


网络层

IP协议

在这里插入图片描述

  • 4位版本:IP协议的版本号 当前只有两个取值 4 和 6 分别代表IPV4 和IPV6
  • 4位首部长度:IP的报头和TCP类似 都是可变的 带有选项的(0-15)15 的实际标识的长度就是60
  • TOS说是8位 可实际有效的只有4位 分别是 最小延时 最大吞吐量 最高可靠性 最小成本
  • 16位总长度 65535 类似于UDP的64k 如果超过64k IP协议自身实现了分包和组包这样的操作
  • 在这里插入图片描述
    这三个字段就是用来分包和组包的
    在这里插入图片描述
    如果整个数据报太长了 IP协议就会把这些数据报分割为多个小包 保证每个不会超过64k
    然后就会按照顺序给小包标记片偏移 并且不是最后一个包的话 标记为为0 如果为最后一个包的话 会更改标记位为1 当标记位为1 的时候 就代表结束标记
    这样接收方就可以根据标记判断是否发送完毕 然后根据片 偏移就可以将小包再次组合为一个数据报

如何基于UDP实现组包分包 就可以照抄IP


  • 8位生存时间 :代表一个IP数据报可以在网络中还能存在多久 但是这个不是按照一个具体的时间来计算的 而且根据转发次数 每经过一次转发其中的时间就会减少1 当其中的值变为0之后 这个包就会丢失 这么做是为了避免出现有些数据报中的IP 可能永远是无法到达的 这样就会被在网络中进行无休止的转发 导致网络拥塞 设置了生存时间就不会出现这种问题了
  • 8位协议 :传输层使用的是哪种协议 TCP或者是UDP都有不同的取值
  • 16位首部校验和:也是用来验证数据是否正确

还是简单的回顾一下IP
源IP表示发件人地址
目的IP表示收件人地址
对于一个IPv4来说 一个IP地址本质上是32位的整数
通常会使用点分十进制来表示这个IP
三个点 把32位整数分成4个部分 每个部分1个字节 每个部分的取值就是0-255
IP地址是一个点分十进制构成的数据
IP地址分成了两个部分 网络号+主机号
网络号描述了当前的网段信息
主机号区分了局域网内部的主机


数据链路层

数据链路层主要的协议 叫做“以太网” 像平时的网线 就叫做“以太网线”
以太网数据帧很简单 就是帧头为一个目的地址和源地址
在这里插入图片描述
其中 这里的地址 可就不是咱们的IP地址啦 这个地址是一个物理地址称为“mac地址”
mac地址做到了每个设备都是唯一的(每个网卡都是唯一的 这些网卡在出厂的时候已经被写死了)
其实ipv4和mac地址是同一时代的产物 当年网络层协议和数据链路层协议是各自独立研发出来的 mac地址和IP地址 有点重复了 IP用来表示一次传输过程中的起点和重点 mac用来表示传输过程中 任意两个相邻节点之间的地址
帧尾就是一个基于CRC算法的校验和 采用的循环冗余算法 把数据的每个字节依次相加 (当然数据很可能会溢出 不过这个没关系 溢出就溢出 没有影响)


物理层

由于物理层距离程序员比较遥远 俺也没有过多的了解 就不做介绍啦~


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

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

相关文章

C语言实现学生管理系统

学习完C语言之后,我们可以通过简单写一个学生管理系统来检验自己学的怎么样。很多计算机系大学生都会学到C语言,对于C语言课程的设计作业可能会感到困难,该篇博客的核心点就是带领读者单独完成学生管理系统,此篇博客附有整个学生管…

【C++ 入坑指南】(11)指针

文章目录 一、概念定义和使用二、空指针 & 野指针2.1 空指针2.2 野指针2.3 小结 三、const 修饰的指针四、指针 和 数组五、指针和函数六、实例 学习 C 的指针既简单又有趣。通过指针,可以简化一些 C 编程任务的执行,还有一些任务,如动态…

数据全生命周期管理

数据存储 时代"海纳百川,有容乃大"意味结构化、半结构和非结构化多样化的海量的 ,也意味着批数据和流数据多种数据形式的存储和计算。面对不同数据结构、数据形式、时效性与性能要求和存储与计算成本等因素考虑,应该使用适合的存储…

组合预测模型 | ARIMA-CNN-LSTM时间序列预测(Python)

组合预测模型 | ARIMA-CNN-LSTM时间序列预测(Python) 目录 组合预测模型 | ARIMA-CNN-LSTM时间序列预测(Python)预测结果基本介绍程序设计参考资料 预测结果 基本介绍 ARIMA-CNN-LSTM是一种结合了传统时间序列模型和深度学习模型的…

chatgpt赋能Python-python3的下载

Python 3-您在编程路上不可或缺的伙伴 如果您正在寻找一种流行的编程语言,那么Python 3就是一个不错的选择。Python 3作为一种高级编程语言,可以轻松地创建各种应用程序和网站。它是最受欢迎的编程语言之一,就是因为它易于学习和使用。 Pyt…

本地部署 VisualGLM-6B

本地部署 VisualGLM-6B 1. 什么是 VisualGLM-6B2. Github 地址3. 安装 Miniconda34. 创建虚拟环境5. 安装 VisualGLM-6B6. 启动 VisualGLM-6B7. 访问 VisualGLM-6B8. API部署9. 命令行部署 1. 什么是 VisualGLM-6B VisualGLM-6B 是一个开源的,支持图像、中文和英文…

大模型时代下智能文档处理核心技术大揭秘

大模型时代下智能文档处理核心技术大揭秘 前言一张图全览文档图像分析与预处理图像预处理的整体架构核心技术点应用场景 版面分析与还原整体架构核心技术点应用场景 AI安全文档图像篡改检测 大模型时代思考总结 前言 最近,中国图像图形大会在苏州圆满结束&#xff0…

碳交易机制下考虑需求响应的综合能源系统优化运行(matlab代码)

目录 1 主要内容 架构模型: 需求响应模型: 目标函数: 2 部分程序 3 程序结果 4 下载链接 1 主要内容 该程序复现文献《碳交易机制下考虑需求响应的综合能源系统优化运行》,解决碳交易机制下考虑需求响应的综合能源系统优化…

Emacs之快速高亮查找字符(九十)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 人生格言: 人生…

ubuntu22.04静态ip设置(桥接模式、only-host+NAT模式)

在创建一台虚拟机后,默认的方式往往是通过DHCP动态的进行分配,DHCP服务器会告知创建的虚拟机分配到的ip地址,网关地址等信息。所以在创建好虚拟机之后,这些信息都不需要我们来配置,我们直接用就好了。 但是&#xff0…

redis集群之hash槽分析算法

上文提过了 hash取余算法和hash一致性算法 一致性hash算法是为了减少节点数目发生改变时尽可能的减少数据迁移 将所有的存储节点排在首位相连的Hash环上,每个key在计算hash后会顺时针找到临近的存储节点。 而当有节点加入或退出时,仅影响该节点在hash环上…

chatgpt赋能Python-python3求平均值

Python3求平均值-从基础到实践 Python3作为一种广泛使用的编程语言,被广泛应用于不同的领域。今天我们将探讨如何使用Python3求平均值。求平均值在数学和统计学中非常常见,使我们能够了解数据的中心趋势,并简化数据分析过程。让我们深入了解…

DELPHI7实现XP菜单风格

在DELPHI7中不使用任何第三方控件,实现放在工具栏上可拖动的XP风格菜单 今天有点空闲时间,顺便写点东西,不是什么深奥的东西,但实用,对于不想第三方控件但又想加点效果的朋友可能有点用.实现的效果如图: 步骤一:把Win32面板上把CoolBar组件加到窗体上 步骤二:把Additional面板上…

VBA 密码删除软件 4n6.VBA Password Remover 1.2 Crack

VBA 密码删除软件 软件评级(基于 1541 条评论的平均评分 4.8) 该工具是完美的软件,可以解锁任何类型的受密码保护的 VBA 文件。用户可以轻松使用此 VBA 密码删除软件并从 VBA 文件中删除密码保护。 兼容所有 Office 文件格式:.d…

Linux线程5——生产消费模型

生产消费模型 1个交易场所:超市 2种角色:生产者/消费者 3种关系:生产者和生产者(竞争关系也叫互斥关系),消费者和消费者(竞争关系同样是互斥关系),生产者和消费者(互斥,同步关系:生产完再消费或消费完再生产)。 以上是生产消费模型遵守的“321”原则。 生产者和消…

RocketMQ Connect 核心知识点概述

一、概览 RocketMQ Connect是RocketMQ数据集成重要组件,可将各种系统中的数据通过高效,可靠,流的方式,流入流出到RocketMQ,它是独立于RocketMQ的一个单独的分布式,可扩展,可容错系统&#xff0…

英文文本情感分析textblob模块sentiment方法

【小白从小学Python、C、Java】 【计算机等考500强证书考研】 【Python-数据分析】 英文文本情感分析 textblob模块 sentiment方法 [太阳]选择题 关于下列代码说法错误的是? from textblob import TextBlob myText"Textblob is amazingly simple to us…

chatgpt赋能Python-python3绝对值

Python3绝对值——学习Python3编程的基础 Python3是一种非常流行的编程语言,可以应用于各种不同的场景,例如数据科学、机器学习、网络编程、自动化脚本、游戏开发等。在Python3编程中,绝对值是一个基础的概念。 什么是绝对值? …

【网络编程】实现UDP/TCP客户端、服务器

目录 一、UDP 1、Linux客户端、服务器 1.1udpServer.hpp 1.2udpServer.cc 1.3udpClient.hpp 1.4udpClient.cc 1.5onlineUser.hpp 2、Windows客户端 二、TCP 1、单进程版的TCP客户端、服务器 1.1tcpServer.hpp 1.2tcpServer.cc 1.3tcpClient.hpp 1.4tcpClient.cc …

K8s进阶1——kubeadm工具搭建K8s高可用集群

文章目录 一、资源清单二、系统初始化2.1 所有服务器配置2.2 master节点配置 三、nginxkeepalived3.1 主备机器上进行3.2 配置主节点3.3 配置备节点3.4 启动服务 四、部署etcd集群4.1 资源清单4.2 生成Etcd证书4.3 部署Etcd集群 五、安装Docker/kubeadm/kubelet5.1 安装docker5…