[Linux][网络][网络层][IP协议]详细讲解

目录


0.基本概念

  • 主机:配有IP地址,但是不进行路由控制的设备
  • 路由器:即配有IP地址,又能进行路由控制
  • 节点:主机和路由器的统称
  • IP协议解决什么问题?
    • 提供一种能力,将数据从主机A送到主机B的能力

1.IP协议头格式

  • 4位版本号(version):指定IP协议的版本,对于IPv4来说,就是4
  • 4位首部长度(header length) :IP头部的长度是多少个32bit,也就是length * 4 的字节数
    • 4bit表示最大的数字是15,因此IP头部最大长度是60字节
  • 8位服务类型(Type Of Service):
    • 3位优先权字段(已经弃用)
    • 4位TOS字段
      • 最小延时
      • 最大吞吐量
      • 最高可靠性
      • 最小成本
      • 这四者相互冲突,只能选择一个
      • 具体选择分场合,比如:对于ssh/telnet这样的应用程序,最小延时比较重要;对于ftp这样的程序,最大吞吐量比较重要
    • 1位保留字段(必须置为0)
  • 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字节):**略

2.IP分片与组装

  • 不同数据链路有个最大的区别,就是它们各自的最大传输单位(MTU:Maximum Transmission Unit)不同
    • MTU的值在以太网中是1500字节,在FDDI中是4352字节,而ATM则为9180字节
    • IP的上一层可能会要求传送比这些MTU更多字节的数据,因此必须在线路上传送比包长还要小的MTU
  • 为了解决这个问题,IP进行分片处理(IP Fragmentation)
    • 顾名思义,所谓分片处理是指,将较大的IP包分成多个较小的IP包
    • 分片的包到了对端目标地址以后会再被组合起来传给上一层
      • 即:从IP的上次层看,它完全可以忽略数据包在途中的各个数据链路上的MTU,而只需要按照源地址发送的长度接收数据包
    • IP就是以这种方式抽象化了数据链路层,使得从上层更不容易看到底层网络构造的细节

1.为什么要分片?

  • 因为数据链路层一次可以向网络里发送的数据大小是有限制的MTU:1500字节
    • **例如:**网络层收到1500个数据,向链路层传递时会添加ip报头20字节,超出1500字节,此时就要分片,分成1480和20,再分别加上ip报头20字节传给链路层

2.分片后谁来组装?

  • 对端网络层

3.这个分片操作传输层知道吗?

  • IP分片和组装的行为,TCP是不知道、不关心的

4.如何识别报文和报文的不同?

  • 通过16位的标识
    • 不同报文,标识不同
    • 相同报文的分片,标识相同

5.接收端,如何得知报文是独立的还是一个分片?

  • 若 更多分片标志位0 && 13位片偏移0,则一定为独立报文

    cpp 复制代码
    if(报文->更多分片 & 0x1)
    {
        return 分片;
    }
    else if(报文->片偏移 > 0)
    {
        return 分片;
    }
    else
    {
        return 独立报文;
    }

6.如何区别哪些分片是开始、中间、结尾?

  • 开始:更多分片1,片偏移0
  • 中间:更多分片1,片偏移 != 0
  • 结尾:更多分片0,片偏移 != 0

7.中间报文有多个,怎么保证收全了?分片后如何组装?

  • 偏移量 + 自身大小 = 下一个报文的偏移量
  • 根据偏移量,来进行升序排序、结合
  • 扫描整个报文如果不匹配,则中间一定会有丢失的,如果成功计算到结尾,就一定收取完整了

8.分片一定好吗?是否分片是谁说了算?

  • 分片行为不是主流 ,严重不推荐分片行为
    • 分片越多,则意味着越大的可能丢包
  • 是否分片由传输层 决定,网络层说了不算
    • 只有传输层可以控制传输数据的大小

3.网段划分

  • IP地址分为两个部分

    • 网络号:保证互相连接的两个网段具有不同的标识
    • 主机号:同一网段内,主机之间具有相同的网络号,但是必须有不同的主机号
  • 不同的子网其实就是把网络号相同的主机放到一起

  • 如果在子网中新增一台主机,则这台主机的网络号和这个子网的网络号一致,但是主机号必须不能和子网中的其他主机重复

  • 通过合理设置主机号和网络号,就可以保证在相互连接的网络中,每台主机的IP地址都不相同

  • 那么问题来了,手动管理子网内的IP,是一个相当麻烦的事情

    • 有一种技术叫做DHCP(Dynamic Host Configuration Protocol),能够自动的给子网内新增主机节点分配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 Inter-domain Routing)

    • 引入一个额外的子网掩码(subnet mask)来区分网络号和主机号
    • 子网掩码也是一个32位的正整数,通常用一串"0"来结尾
    • 将IP地址和子网掩码进行"按位与"操作,得到的结果就是网络号
    • 网络号和主机号的划分与这个IP地址是A类、B类还是C类无关
  • 目的IP & 当前路由器的子网掩码 = 该报文要去的目的网络

    • 因为不同的路由器一定至少要级联2个网络
    • 每一个网络的网络号可能是不同的
    • 每个路由器都要给自己直接链接的网络都要配置对应的子网掩码
  • 以下为两个例子

  • 可见,IP地址与子网掩码做与运算可以得到网络号,主机号从全0到全1就是子网的地址范围

  • IP地址和子网掩码还有一种更简洁的表示方法

    • 例如140.252.20.68/24
      • 表示IP地址为140.252.20.68
      • 子网掩码的高24位是1,也就是255.255.255.0
      • 网络号占据24个比特位

4.特殊的IP地址

  • 将IP地址中的主机地址全部设为0,就成为了网络号,代表这个局域网
  • 将IP地址中的主机地址全部设为1,就成为了广播地址,用于给同一个链路中相互连接的所有主机发送数据包
  • 127.*的IP地址用于本机环回(loop back)测试,通常是127.0.0.1

5.IP地址的数量限制

  • IP地址(IPv4)是一个4字节32位的正整数,那么一共只有2^32个IP地址,大概是43亿左右
    • 而TCP/IP 协议规定,每个主机都需要有一个IP地址
  • 这意味着,一共只有43亿台主机能接入网络么?
    • 实际上,由于一些特殊的IP地址的存在,数量远不足43亿
    • 另外IP地址并非是按照主机台数来配置的,而是每一个网卡都需要配置一个或多个IP地址
  • CIDR 在一定程度上缓解了IP地址不够用的问题(提高了利用率,减少了浪费,但是IP地址的绝对上限并没有增加),仍然不是很够用,这时候有三种方式来解决
    • **动态分配IP地址:**只给接入网络的设备分配IP地址,因此同一个MAC地址的设备,每次接入互联网中,得到的IP地址不一定是相同的
    • NAT技术
    • IPv6:
      • IPv6并不是IPv4的简单升级版,这是互不相干的两个协议,彼此并不兼容
      • IPv6用16字节128位来表 示一个IP地址,但是目前IPv6还没有普及

6.私有IP地址和公网IP地址

  • 如果一个组织内部组建局域网,IP地址只用于局域网内的通信,而不直接连到Internet上,理论上 使用任意的IP地址都 可以,但是RFC 1918规定了用于组建局域网的私有IP地址
    • 10.* 前8位是网络号,共16,777,216个地址
    • 172.16.到172.31. 前12位是网络号,共1,048,576个地址
    • 192.168.* 前16位是网络号,共65,536个地址,包含在这个范围中的,都成为私有IP,其余的则称为全局IP(公网IP)
  • 一个路由器可以配置两个IP地址
    • WAN口IP:自己所在上级子网给自己分配的IP
    • LAN口IP(子网IP):局域网IP
  • 路由器LAN口连接的主机,都从属于当前这个路由器的子网中
  • 不同的路由器,子网IP其实都是一样的(通常都是192.168.1.1),子网内的主机IP地址不能重复,但是子网之间的IP地址就可以重复了
  • 每一个家用路由器,其实又作为运营商路由器的子网中的一个节点,这样的运营商路由器可能会有很多级,最外层的运营商路由器,WAN口IP就是一个公网IP了
  • 子网内的主机需要和外网进行通信时,路由器将IP首部中的IP地址进行替换(替换成WAN口IP),这样逐级替换,最终数据包中的IP地址成为一个公网IP,这种技术称为NAT(Network Address Translation,网络地址转换)

7.路由

  • 在复杂的网络结构中,找出一条通往终点的路线

  • 路由的过程,就是这样一跳一跳(Hop by Hop)"问路"的过程

    • 所谓"一跳"就是数据链路层中的一个区间,具体在以太网中指从源MAC地址到目的MAC地址之间的帧传输区间
  • IP数据包的传输过程也和问路一样

    • 当IP数据包,到达路由器时,路由器会先查看目的IP
    • 路由器决定这个数据包是能直接发送给目标主机,还是需要发送给下一个路由器
    • 依次反复,一直到达目标IP地址
  • 那么如何判定当前这个数据包该发送到哪里呢?这个就依靠每个节点内部维护一个路由表

    • 为了将数据包发给目标主机,所有主机都维护着一张路由控制表(Routing Table)
    • 该表记录IP数据在下一步应该发给哪个路由器。IP包将根据这个路由表在各个数据链路上传输

  • 路由表可以使用route命令查看

    • Destination是目的网络地址
    • Genmask是子网掩码
    • Gateway是下一跳地址
    • Iface是发送接口
    • Flags中
      • U标志表示此条目有效
      • G标志表示此条目的下一跳地址是某个路由器的地址,没有G标志的条目表示目的网络地址是与本机接口直接相连的网络,不必经路由器转发
  • 如果目的IP命中了路由表,就直接转发即可

  • 路由表中的最后一行,主要由下一跳地址和发送接口两部分组成,当目的地址与路由表中其它行都不匹配时,就按缺省路由条目规定的接口发送到下一跳地址

  • 假设某主机上的网络接口配置和路由表如下

    • 这台主机有两个网络接口,一个网络接口连到192.168.10.0/24网络,另一个网络接口连到192.168.56.0/24网络
  • 转发过程例1:如果要发送的数据包的目的地址是192.168.56.3

    • 跟第一行的子网掩码做与运算得到192.168.56.0,与第一行的目的网络地址不符
    • 再跟第二行的子网掩码做与运算得到192.168.56.0,正是第二行的目的网络地址,因此从eth1接口发送出去
    • 由于192.168.56.0/24正是与eth1接口直接相连的网络,因此可以直接发到目的主机,不需要经路由器转发
  • **转发过程例2:**如果要发送的数据包的目的地址是202.10.1.2

    • 依次和路由表前几项进行对比,发现都不匹配
    • 按缺省路由条目,从eth0接口发出去,发往192.168.10.1路由器
    • 由192.168.10.1路由器根据它的路由表决定下一跳地址
相关推荐
小糖学代码1 小时前
Linux:11.线程概念与控制
linux·服务器·c语言·开发语言·c++
YouEmbedded4 小时前
解码Linux文件IO目录检索与文件属性
linux·文件属性·文件io·目录检索
大聪明-PLUS8 小时前
关于新的 Linux 内核接口 gpio uapi 的说明
linux·嵌入式·arm·smarc
玉树临风江流儿8 小时前
Linux驱动开发总结速记
linux·运维·驱动开发
cccyi78 小时前
Linux 进程信号机制详解
linux·signal·volatile
Hello.Reader8 小时前
Flink 受管状态的自定义序列化原理、实践与可演进设计
java·网络·flink
gd63213749 小时前
银河麒麟 aarch64 linux 里面的 qt 怎么安装kit
linux·服务器·qt
A-花开堪折9 小时前
Qemu 嵌入式Linux驱动开发
linux·运维·驱动开发
磊灬泽9 小时前
【Linux驱动开发】PWM子系统-servo
linux·运维·算法
郝学胜-神的一滴10 小时前
Linux系统函数stat和lstat详解
linux·运维·服务器·开发语言·c++·程序人生·软件工程