目录

一、IP 服务的特点

IP 协议为上层协议提供无状态、无连接、不可靠的服务:

  • 无状态(stateless):指 IP 通信双方不同步传输数据的状态信息,因此所有 IP 数据报的发送、传输和接收都是相互独立的、没有上下文关系。

    • 缺点:无法处理乱序和重复的 IP 数据报,对于上层协议来说,收到的信息可能是乱序的、重复的;
    • 优点:简单、高效,无需为保持通信的状态而分配一些内核资源,也无需每次传输数据时都携带状态信息。
  • 无连接(connectionless):指 IP 通信双方都不长久地维持对方的任何信息,因此上层协议每次发送数据时都需要明确指定对方的 IP 地址;
  • 不可靠:IP 协议不能保证 IP 数据报准确地到达接收端,只是尽最大努力(best effort)。

二、IPv4 结构

  • 4 位版本号(version):指定协议版本,对 IPv4 来说就是 4 ;
  • 4 位头部长度(header length):标识该 IP 头部有多少个 32 bit 字,由于 4 位最大能表示 15 ,因此 IP 头部最长为 60 字节;
  • 8 位服务类型(Type Of Service,TOS):包括一个 3 位的优先权字段(现已忽略),4 位的 TOS 字段和 1 位保留字段(必须置 0)。其中 4 位的 TOS 字段分别表示:最小时延、最大吞吐量、最高可靠性、最小费用,其中最多有一个能置为 1 ,应用程序应该根据实际需要来设置它;
  • 16 位总长度(total length):指整个 IP 数据报的长度,以字节为单位,因此 IP 数据报的最大长度为 65535( 2 16 − 1 2^{16}-1 216−1)字节。但由于 MTU 的限制,长度超过 MTU 的数据报都将被分片传输,所以实际传输的 IP 数据报(或分片)的长度都远远没有达到最大值;
  • 16 位标识(identification):唯一地表示主机发送的每一个数据报,初始值由系统随机生成,每发送一个数据报就加 1 ,该值在数据包分片时被复制到每个分片中,因此同一个数据报的所有分片都具有相同的标识值;
  • 3 位标志:
    • 第一位:保留;
    • 第二位(Don’t Fragment,DF):表示禁止分片,如果设置则不会分片。这种情况下如果 IP 数据报文长度超过 MTU ,将会丢弃该数据并返回一个 ICMP 差错报文;
    • 第三位(More Fragment,MF):表示“更多分片”,除数据报的最后一个分片外,其他分片都要把它置为 1 。
  • 13 位分片偏移(fragmentation offset):分片相对于原始 IP 数据报开始处(仅指数据部分)的偏移。实际的偏移值是该值左移 3 位(乘 8)后得到的。因此除最后一个 IP 分片外,每个 IP 分片的数据部分的长度必须是 8 的整数倍。
  • 8 位生存时间(Time To Live,TTL):是数据报到达目的地之前允许经过的路由器跳数,被发送端设置(常为 64).没经过一个路由,该值就被减 1 ,当它减为 0 时,路由器将丢弃数据报并向源端发送一个 ICMP 差错报文。该值可以防止数据报陷入路由循环。
  • 8 位协议(protocol):用于区分上层协议,ICMP 是 1 ,TCP 是 6 ,UDP 是 17 ;
  • 16 位头部校验和(header checksum):由发送端填充,接收端对其使用 CRC 算法以检验 IP 数据报头部(仅用于头部)在传输过程中是否损坏;
  • 32 位源端 IP 地址、目的端 IP 地址:用于标识数据报的发送端和接收端,一般情况下这两个地址在整个传输过程中保持不变;
  • 选项(option):可变长的可选信息,最多包含 40 字节(IP 头部最长为 60 字节,去除前面的 20 字节还剩 40 字节):
    • 记录路由(record route):告诉数据报途径的所有路由器都将自己的 IP 地址填入,这样可以跟踪数据报的传递路径;
    • 时间戳(timestamp):告诉每个路由器都将数据报被转发的时间(或时间与 IP 地址对)填入,这样可以测量途经路由之间数据报传输的时间;
    • 松散源路由选择(loose source routing):指定一个路由器 IP 地址列表,数据报发送过程中必须经过其中所有的路由器;
    • 严格源路由选择(strict source routing):与上一条类似,不过数据报只能经过被指定的路由器。

三、IP 分片

分片可能发生在发送端,也可能发生在中转路由器上,而且可能在传输过程中被多次分片,但只有在最终的目标机器上,这些分片才会被内核中的 IP 模块重新组装。

以太网帧的 MTU 是 1500 字节,因此它携带的 IP 数据报的数据部分最多是 1480 字节(IP 头部占用 20 字节)。考虑用 IP 数据报封装一个长度为 1481 字节的 ICMP 报文(包括 8 字节的 ICMP 头部,所以其数据部分长度为 1473 字节),则该数据报再使用以太网帧传输时必须被分片:

四、IP 路由


从右往左分析,首先获取 IP 数据报,经 CRC 检测无误后,分析头部具体信息,如果设置了原站选路选项(松散、严格),则 IP 模块调用数据报转发子模块来处理该数据报。如果该 IP 数据报的头部中目标 IP 地址是本机的某个地址(或广播地址),则交给上层应用;否则也调用数据报转发子模块处理。

数据报转发子模块将首先检测系统是否允许转发,如果不允许就丢弃,反之则对其执行一些操作,然后将其交给 IP 数据报输出子模块。

IP 数据报应该发送至哪个下一跳路由,以及通过哪个网卡发送,就是 IP 路由过程(即图中计算下一跳路由模块)。IP 模块实现数据报路由的核心数据结构是路由表,此表按照数据报的目标 IP 地址分类,同一类型的 IP 数据报将被发往相同的下一跳路由器。

IP 输出队列中存放的是所有等待发送的 IP 数据报,其中除了需要转发的 IP 数据报外,还包括封装了本机上层数据的报文。

虚线箭头表示路由表更新的过程,这一过程是指通过路由协议或者 route 命令调整路由表,使之更适应最新的网络拓扑结构,称为 IP 路由策略。

要了解 IP 路由机制,就需要先了解路由表:

字段 含义
Destination 目标网络或主机
Gateway 网关地址,* 表示目标和本机在同一个网络,不需要路由
Genmask 网络掩码
Flags 路由项标志,有 5 种
Metric 路由距离,即到达指定网络所需的中转数
Ref 路由项被引用的次数(Linux 中未使用)
Use 该路由项被使用的次数
Iface 该路由项对应的输出网卡接口

其中,路由项标志有 5 种:

  • U:该路由项是活动的;
  • H:该路由项的目标是一台主机;
  • G:该路由项的目标是网关;
  • D:该路由项是由重定向生成的;
  • M:该路由项是被重定向修改过的。

路由表按照 IP 地址分类的规则称为 IP 路由机制,分为 3 个步骤:

  • 步骤 1:查找路由表中和数据报的目标 IP 地址完全匹配的主机 IP 地址,如果找到就是用该路由项,否则转到步骤 2 ;
  • 步骤 2:查找路由表中和数据报的目标 IP 地址具有相同网络 ID 的网络 IP 地址,如果找到就是用该路由项,否则转到步骤 3 ;
  • 步骤 3:选择默认路由项,这通常意味着数据报的下一跳路由是网关。

由于网络是实时变化的,因此路由表必须能够实时更新。通过 route 命令或其他手工修改路由表的方式称为静态路由的更新方式;而对于大型路由器则常通过 BGP(Border Gateway Protocol,边际网关协议)、RIP(Routing Information Protocol,路由信息协议)、OSPF 等协议来更新,称为动态路由的更新方式。

五、IP 转发

前文中提到,不是发送给本机的 IP 数据报将由数据报转发子模块来处理,这称之为 IP 转发,路由器都能执行数据报转发操作,而主机一般只发送或接受数据报,这是因为 /proc/sys/net/ipv4/ip_forward 内核参数默认被设置为 0 ,将其修改为 1 可使主机具备数据转发功能。

对于允许 IP 数据报转发的系统,数据报转发子模块将对期望转发的数据报执行如下操作:

  1. 检查数据包头部的 TTL 值,若为 0 ,则丢弃;
  2. 查看数据报头部的严格源路由选择选项,若被设置则检测数据报的目标 IP 地址是否是本机的某个 IP 地址;若不是则发送一个 ICMP 源站选路失败报文给发送端;
  3. 如果有必要,则给源端发送一个 ICMP 重定向报文,告诉它一个更合适的下一跳路由;
  4. 将 TLL 值减 1 ;
  5. 处理 IP 头部选项;
  6. 如果有必要,则执行 IP 分片操作。

六、重定向

由图 2-3 可以发现 ICMP 重定向报文也能用于更新路由表:

  • 8 位类型:用于区分报文类型:

    • 差错报文:主要用来回应网络错误,比如目标不可达(类型值为 3)和重定向(类型值为 5);
    • 查询报文:查询网络信息,如 ping (类型为 8);
    • 重定向报文:类型为 5 。
  • 8 位代码:有 4 个可选值,本文仅讨论主机重定向
    • 重定向报文使用代码值 0 表示对网络重定向;
    • 代码值 1 表示对主机重定向;
  • 16 位校验和:对整个报文进行 CRC 校验;
  • 数据部分:
    • 引起重定向的 IP 数据报(原始 IP 数据报)的源端 IP 地址;
    • 应该使用的路由器的 IP 地址。

接受主机根据数据部分的两个信息就可以断定引起重定向的 IP 数据报应该使用哪个路由器来转发,并且以此来更新路由表(通常是更新路由表缓冲,而不是直接更改路由表)。

/proc/sys/net/ipv4/conf/all/send_redirects 内核参数指定是否允许发送 ICMP 重定向报文,/proc/sys/net/ipv4/conf/all/accept_redirects 内核参数则指定是否允许接收 ICMP 重定向报文,一般来说,主机只能接受,路由器只能发送。

七、IPv6 结构

IPv4 存在地址不够用等问题,因此发展出了 IPv6 协议,相对于 IPv4 做了很大改进:

  • 4 位版本号(version):指定 IP 协议的版本,值为 6 ;
  • 8 位通信类型(traffic class):指示数据流通信类型或优先级,和 IPv4 中的 TOS 类似;
  • 20 位流标签(flow label):新增字段,用于某些对连接的服务质量有特殊要求的通信,比如音视频实时传输;
  • 16 位净荷长度(payload length):指 IPv6 扩展头部和应用程序数据长度之和,不包括固定头部长度;
  • 8 位下一个包头(next header):指出紧跟 IPv6 固定头部的包类型,如扩展头(如果有的话)或某个上层协议头(TCP、UDP、ICMP),类似于 IPv4 头部中的协议字段,且相同的取值有相同的含义;
  • 8 位跳数限制(hop limit):和 IPv4 中的 TTL 含义相同;
  • 128 位源端/目的端 IP 地址:采用 128 位使得 IP 地址总量达到 2 128 2^{128} 2128 个。

IPv4 地址为 32 位,因此通常使用点分十进制表示,而 IPv6 地址通常使用十六进制字符串表示:FE80:0000:0000:0000:1234:5678:0000:0012 。由于这种表示方法过于麻烦,通常可将 0 进行压缩:FE80::1234:5678:0000:0012 ,注意,0 压缩表示只能使用 1 次,否则无法计算 :: 之间有多少个全 0 组。

可变长的扩展头部使得 IPv6 能支持更多的选项,最小可以为 0 ,一个数据报可以包含多个扩展头部,每个扩展头部的类型由前一个头部(固定头部或扩展头部)中的下一个报头字段指定:

扩展头部 含义
Hop-by-Hop 逐跳选项头部,包含每个路由器都必须检查和处理的特殊参数选项
Destination options 目的选项头部,指定由最终目的节点处理的选项
Routing 路由头部,指定数据报要经过哪些中转路由器,功能类似于 IPv4 的松散源路由选择和记录路由选项
Fragment 分片头部,处理分片和重组的细节
Authentication 认证头部,提供数据源认证、数据完整性检查和反重播保护
Encapsulating Security Payload 加密头部,提供加密服务
No next header 没有后续扩展头部

IPv6 协议并不是 IPv4 协议的简单扩充,而是完全独立的协议,用以太网帧封装的 IPv6 数据报和 IPv4 数据报具有不同的类型值,前者为 0x86dd ,后者为 0x800 。

Linux 网络编程学习笔记——二、IP 协议详解相关推荐

  1. [Linux网络编程学习笔记]索引

    一.Linux基本知识 [学习笔记]Linux平台的文件I/O操作 [学习笔记]Linux平台的文件,目录及操作 [Linux学习笔记]标准输入输出 [Linux学习笔记]进程概念及控制 [Linux ...

  2. 编程开发:Linux网络编程学习笔记

    非常全面.通俗易懂.值得借鉴的Linux网络编程学习笔记.关键字:linux linux编程 网络编程 linux网络编程 下载地址:点我下载 特别说明:本资源收集于网络,版权归原作者及版权商所有,仅 ...

  3. Linux 网络编程学习笔记

    前言: 本文是学习<Linux 高性能服务器编程(游双 著)>时所记录的重点知识. 一.TCP/IP 协议族 二.IP 协议详解 三.TCP 协议详解 四.HTTP 通信 五.Linux ...

  4. [Linux网络编程学习笔记]套接字地址结构

    好久没有看那Linux网络编程这本书了,今天看到了重点部分-TCP套接字.下面先来看看套接字的地址结构 Linux系统的套接字可以支持多种协议,每种不同的协议都是用不同的地址结构.在头文件<li ...

  5. Linux网络编程学习笔记

    声明:1.未经过原作者许可,不可用于商业行为:2.本笔记仅用于知识学习,如有侵权,立即删除. 1.学习链接 黑马程序员-Linux网络编程:https://www.bilibili.com/video ...

  6. Linux 网络编程学习笔记——三、TCP 协议详解

    目录 一.TCP 服务的特点 传输层协议主要有 TCP 协议和 UDP 协议,前者相对于后者的特点是:面向连接.字节流和可靠传输. 使用 TCP 协议通信的双方必须先建立连接,然后才能开始数据的读写. ...

  7. Linux网络编程学习笔记(TCP)

    文章目录 1 字节序 1.1 定义 1.2 字节序转换函数 2 Socket地址 2.1 通用socket地址(实际开发不使用) 2.2 专用socket地址 2 IP地址转换 3 TCP通信流程 3 ...

  8. 【Linux网络编程】因特网的IP协议是不可靠无连接的,那为什么当初不直接把它设计为可靠的?

    因特网使用的IP协议是无连接的,因此其传输是不可靠的.这样容易使人们感到因特网很不可靠,那为什么当初不直接把它设计为可靠的? 先打一个比方.邮局寄送的平信很像无连接的IP数据报.每封平信可能走不同的传 ...

  9. Linux网络编程(网络层)-ip协议/地址管理/路由选择

    网络层:负责地质管理与路由选择 IP协议: 注: udp报文大小大于MTU,则会在网络层进行数据分片,分割成多个小的数据分片进行传输 MTU:最大传输单元 (链路层所限制的一个最大数据帧大小)以太网默 ...

最新文章

  1. c++ double float 数值比较
  2. Allegro 如何把铺好铜皮的平面层互换
  3. Error assembling WAR: webxml attribute is required (or pre-existing WEB-INF/web.xml
  4. Quick BI电子表格: 新手亦可表格自由
  5. Python json模块 - Python零基础入门教程
  6. python elif可以单独使用_elif可以单独使用。( )_学小易找答案
  7. XCode 7.3.1(dmg) 官方直接下载地址
  8. Cocos2d-x 3.X手游开发实例详解
  9. oracle 同义词_详解Oracle视图V$、GV$、X$、V_$、GV_$之间的关系
  10. 性能测试--jmeter中HTTP Cookie管理器的使用【18】
  11. 王道数据结构代码---第五章:二叉树(重要)
  12. Java-----四舍五入保留两位小数的方法
  13. 汇丰银行的华尔街恐怖故事
  14. [笔记]VMware常见问题
  15. 怎样用N多小图片拼成一张大图?(数字图像处理)
  16. 大学生观看直播时长影响因素分析
  17. 在VIVIDO中快速计算并输入N多个多字节数值(2J)
  18. 30. 主频和时钟配置实验
  19. 组合数的计算方法(Combinatorial Number)
  20. 屏幕录制的免费工具camstudio

热门文章

  1. 苹果第一次怼了华为 是因为抢跑5G的华为走上了苹果模式?
  2. 安卓应用开发小程序!字节跳动+京东+360+网易面试题整理,聪明人已经收藏了!
  3. # Conda environment for TensorFlow and ROOT(HEP) in Mac (M1)
  4. 怎样对平面中的点进行顺时针或者逆时针排序
  5. linux firefox严重卡顿,火狐浏览器卡顿怎么办 卡顿解决方法一览
  6. No module named ‘pip._internal.vcs.git
  7. `Supimo` `Algorithm` 算法代码模板CodeTemplate
  8. 斗地主老是输?一起用Python做个自动出牌器,欢乐豆蹭蹭涨!
  9. AVB传输协议数据包分析
  10. 计算机在储存波形,安泰示波器维修分享--泰克数字示波器的存储功能详解