• 网络层--IP协议


    引入:

    🙋‍IP协议解决什么问题呢 ?

    IP协议提供一种将数据从A主机送到B主机的能力。而 传送过程中的可靠性就依靠 传输层啦,详情可以参考 通过密码学了解安全性  和  TCP 的安全机制 

    IP协议基本概念

    主机  : 配有IP地址, 但是不进行路由控制的设备;

    路由器: 即配有IP地址, 又能进行路由控制;

    节点  : 主机和路由器的统称。

    IP协议头格式

      1. 如何封装和解包呢?

            定长报头+自描述字段(4位首部长度)

      2. 如何交付?(如何确定交付的协议)

            8位协议:标识UDP还是TCP

    4位版本:

    确定是IPv6还是IPv4

    4位首部长度

    IP头部的长度是多少个32bit, 也就是 length * 4 的字节数. (基本单位是4字节)4bit表示最大
    的数字是15, 因此IP头部最大长度是60字节. 当4位首部长度值为 0101 时表示没有选项(20字节)

    8位服务类型(Type Of Service):

    3位优先权字段(已经弃用), 4位TOS字段, 和1位保留字段(必须置为0).
            4位TOS分别表示: 最小延时, 最大吞吐量, 最高可靠性, 最小成本. 这四者相互冲突, 只能选择一个. 对于 ssh/telnet这样的应用程序, 最小延时比较重要; 对于ftp这样的程序, 最大吞吐量比较重要.

    16位总长度(total length):

    IP数据报整体占多少个字节.

    16位标识(id):

    唯一的标识主机发送的报文. 如果IP报文在数据链路层被分片了, 那么每一个片里面的这个
    id都是相同的.

    3位标志:

    第一位保留(保留的意思是现在不用, 但是还没想好说不定以后要用到). 第二位置为1表示禁
    止分片, 这时候如果报文长度超过MTU, IP模块就会丢弃报文. 第三位表示"更多分片", 如果分片了的话, 最后一个分片置为1, 其他是0. 类似于一个结束标记

    13位分片偏移(framegament offset):

    是分片相对于原始IP报文开始处的偏移. 其实就是在表示当前分片在原报文中处在哪个位置. 实际偏移的字节数是这个值 * 8 得到的. 因此, 除了最后一个报文之外, 其他报文的长度必须是8的整数倍(否则报文就不连续了).

    8位生存时间(Time To Live, TTL):

    数据报到达目的地的最大报文跳数. 一般是64. 每次经过一个路由, TTL-= 1, 一直减到0还没到达, 那么就丢弃了. 这个字段主要是用来防止出现路由循环。

    8位协议:

    表示上层协议的类型

    16位头部校验和:

    使用CRC进行校验, 来鉴别头部是否损坏.出错就会丢弃报文。

    32位源地址和32位目标地址:

    表示发送端和接收端.

    选项字段(不定长, 最多40字节): 

    分片:

    链路层因为其物理特性的原因,一般不会一次性转发太大的数据==>也就是说:

    链路层有一次可以转发到网络中的报文大小的限制,一般是1500(MTU),所以网络层需要将一个较大的ip报文拆分成多个小的,符合条件的报文,这就是分片。

    分片的行为是网络层完成的,上层的传输层和应用层并不知道,(这在一定程度上埋下隐患),同样组装的行为也必须由对方的网络层完成。

       为什么呢?

    原因可以分为2个:

      1 、 对方给自己的是一个完整的TCP报文,那我自己上传输层交付时也必须是一个完整TCP报文;

            2 、 协议具有一致性,IP协议负责分片和组装不会影响其他层的服务。

    分片决定了网络层IP协议具有3种能力

    1. 具有区分不同报文的能力      ----16位标识符

    2. 具有判断报文是不是分片的能力   ----“更多分片”

    3. 异常处理             ---- 任何一个分片丢失,都可以识别出来

      怎么做到分片的呢?

    3位标志中有一位是保留的,第2位为1时表示禁止分片,如果报文长度超过MTC,IP就会丢弃报文。第3位 表示 “ 更多分片 ” ,如果分片了的化,最后一个分片置为 0, 其他是 1,类似一个结束标记。

    认识偏移量

    开始: 更多分片 1 ,片偏移 = 0

    结尾: 更多分片 0 ,片偏移 ≠ 0

    中间: 更多分片 1 ,片偏移 ≠ 0

      中间那么多的分片,如何确定所有分片都收到了呢?

    根据偏移量进行升序排序,结合偏移量+自身大小=下一个报文的偏移量,通过扫描整个报文,来进行判断,如果不匹配,则说明报文出现了丢失,需要重新发送,如果成功遍历到结尾,则表明收取到了完整的报文。

    分片之前,报文一定是一个完整的报文分片之后,每一个分片也有单独的IP报头

    下面简单分析一下分片过程

    假设MTC=1500

    原本的整个报文数据大小是 3000 ,(注意: IP报文=IP报头+有效载荷)

    第一步,先分一个1500的数据块,直接拿走原本的报头(实际可能更复杂哈) ,

    剩下的1500的数据并不是可以直接就成为一个分片,还要添加报头信息(20字节)为了支持未来的组装,每一个分片都必须有IP报头,所有分割1480的大小,再添加20字节的报头,最后一个分片包含20字节的报头和20字节的有效载荷。

    我们再来分析一下这三个报文

    报文编号123
    16位标识123412341234
    3位标志“更多分片”110
    13位片偏移015002980
    总长度1500150040

    分片的坏处

    之前我们提到在网络层进行分片和组装,上层是不知道的,同时,我们也应该有这个常识:

    丢包是有概率的,分包会增加报文个数,在一定程度上增加了丢包的概率。,要彻底解决丢包问题,还得依靠 传输层。当然这也决定了分片不是主流

    网段划分

    IP 地址分为两个部分 , 网络号和主机号
            网络号: 保证相互连接的两个网段具有不同的标识 ;
            主机号: 同一网段内 , 主机之间具有相同的网络号 , 但是必须有不同的主机号 ;
    不同的子网其实就是把网络号相同的主机放到一起. 如果在子网中新增一台主机, 则这台主机的网络号和这个子网的网络号一致, 但是主机号必须不能和子网中的其他主机重复.
    通过合理设置主机号和网络号 , 就可以保证在相互连接的网络中 , 每台主机的 IP 地址都不相同 .
    那么问题来了 , 手动管理子网内的 IP, 是一个相当麻烦的事情 .
    有一种技术叫做 DHCP , 能够自动的给子网内新增主机节点分配 IP 地址 , 避免了手动管理 IP 的不便 . 一般的路由器都带有DHCP 功能 . 因此路由器也可以看做一个 DHCP 服务器 .
    过去曾经提出一种划分网络号和主机号的方案 , 把所有 IP 地址分为五类 , 如下图所示
    A类0.0.0.0到127.255.255.255
    B类128.0.0.0到191.255.255.255
    C类192.0.0.0到223.255.255.255
    D类224.0.0.0到239.255.255.255
    E类240.0.0.0到247.255.255.255
    随着 Internet 的飞速发展 , 这种划分方案的局限性很快显现出来 , 大多数组织都申请 B 类网络地址 , 导致 B 类地址很快就
    分配完了 , A 类却浪费了大量地址 ;
    例如 , 申请了一个 B 类地址 , 理论上一个子网内能允许 6 5 千多个主机 . A 类地址的子网内的主机数更多 . 然而实际网络架设中, 不会存在一个子网内有这么多的情况 . 因此大量的 IP 地址都被浪费掉了 .
    针对这种情况提出了新的划分方案 , 称为 CIDR(Classless Interdomain Routing):
    引入一个额外的子网掩码 (subnet mask) 来区分网络号和主机号 ;
    子网掩码也是一个32 位的正整数 . 通常用一串 "0" 来结尾 ;
    IP 地址和子网掩码进行 " 按位与 " 操作 , 得到的结果就是网络号 ;
    网络号和主机号的划分与这个 IP 地址是 A 类、 B 类还是 C 类无关 ;
    示例1
    可见 ,IP 地址与子网掩码做与运算可以得到网络号 , 主机号从全 0 到全 1 就是子网的地址范围 ;
    IP 地址和子网掩码还有一种更简洁的表示方法 , 例如 140.252.20.68/24, 表示 IP 地址为 140.252.20.68, 子网掩码的高24位是 1, 也就是 255.255.255.0

    特殊的IP地址

    IP 地址中的主机地址全部设为 0, 就成为了网络号 , 代表这个局域网 ;
    IP 地址中的主机地址全部设为 1, 就成为了广播地址 , 用于给同一个链路中相互连接的所有主机发送数据包;
    127.* IP 地址用于本机环回 (loop back) 测试 , 通常是 127.0.0.1
  • 相关阅读:
    【Java】Scanner.nextLine() 返回空行/不起作用(吸收换行符)
    竞赛选题 深度学习手势识别 - yolo python opencv cnn 机器视觉
    接口自动化测试:pytest基础讲解
    java通配符有哪些
    python java开发的气象数据采集的系统
    魔众智能AI系统v2.1.0版本支持主流大模型(讯飞星火、文心一言、通义千问、腾讯混元、Azure、MiniMax、Gemini)
    从零学习开发一个RISC-V操作系统(一)丨计算机组成原理相关知识与RISC-V指令集简介
    c++运算符重载
    强化深度学习中使用Dyna-Q算法确定机器人问题中不同规划的学习和策略实战(超详细 附源码)
    7. Spring Boot Profile(多环境配置)
  • 原文地址:https://blog.csdn.net/qq_59293418/article/details/132792492