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

news/2024/3/28 21:45:02/文章来源:https://blog.csdn.net/qq_42375636/article/details/129675870

一、IP 服务的特点

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

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

二、IPv4 结构

1

  • 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(216−12^{16}-12161)字节。但由于 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 字节),则该数据报再使用以太网帧传输时必须被分片:
2

四、IP 路由

3
从右往左分析,首先获取 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 重定向报文也能用于更新路由表:

4

  • 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 做了很大改进:

5

  • 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 地址总量达到 21282^{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 。

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

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

相关文章

Redis五种核心数据结构的基本使用与应用场景

文章目录五种核心数据结构StringHashListSetZset五种核心数据结构 String 常用操作 # 存入字符串键值对 SET key value# 批量存储字符串键值对 MSET key value [key value ...] # 存入一个不存在的字符串键值对 SETNX key value# 获取一个字符串键值 GET key# 批量获…

外贸网站排名优化,掌握这些技巧让你事半功倍!

作为一名外贸网站站长,我们都希望自己的网站能够排名靠前,从而吸引更多的潜在客户,提高网站的流量和转化率。 但是,想要在谷歌搜索引擎中取得好的排名并不是一件容易的事情。 在这篇文章中,我将分享一些我个人的经验…

JMM解析(java内存模型)

1.JMM 主要定义了对于一个共享变量,另一个线程对这个共享变量执行写操作后,这个线程对这个共享变量的可见性。 2.JMM和JVM的区别: JMM是用于高并发的,抽象了线程和主存之间的关系,比如线程之间共享的变量必须存储在…

代码随想录算法训练营第四十八天|198.打家劫舍、213.打家劫舍II、337.打家劫舍III

LeetCode 198 打家劫舍题目链接:https://leetcode.cn/problems/house-robber/思路:dp数组的含义dp[i]表示前i个房间(包括第i个房间)所能偷到的最大金额递推公式有两种情况:1、偷了第i个房间那么此时第i-1个房间肯定是不…

Python基础之操作mysql数据库

Python 标准数据库接口为 Python DB-API,Python DB-API为开发人员提供了数据库应用编程接口。Python 数据库接口支持非常多的数据库,你可以选择适合你项目的数据库:GadFlymSQLMySQLPostgreSQLMicrosoft SQL Server 2000InformixInterbaseOrac…

一、简单了解ElasticSearch

目录一、ElasticSearch简介1.ES与关系型数据库对比2.什么是全文检索3.分词原理(基于倒排索引)二、核心概念1.索引index2.映射mapping3.字段filed4.字段类型type5.文档document6.集群cluster7.节点node8.分片9.副本三、搭建es单机版、集群版1.搭建es2.集成…

项目质量管理工作 不得不重视的4大关键点

1、三大视角确保项目质量 我们需要从客户视角、SOW视角和组织视角三大视角,确保项目的质量。 从客户视角方面出发,满足客户的要求,如项目交付的准时性、项目质量的保证等。我们需要全力保障客户对项目质量的要求。 从SOW视角确保项目质量&…

ffpmeg笔记:(2)学习一个开源小demo:qt+sdl+ffmpeg,计算时间戳

文章目录前言1.源码和编译方法1.1编译方法:2.源码简单介绍2.1 播放线程类 PlayThread2.1.1 计算当前播放进度时间2.2 主界面类 MainWindow2.2.1 在Qt widget中显示视频2.2.2 控制区域的自动隐藏和再现前言 这个小demo实现了下面的功能: 1.打开文件。 2.…

操作系统(2.4.5)--管程机制

1.管程的定义 利用共享数据结构抽象地表示系统中的共享资源,而把对该共享数据结构实施的操作定义为一组过程进程对共享资源的申请、释放和其它操作,都是通过这组过程对共享数据结构的操作来实现的,这组过程还可以根据资源的情况,或…

跟着本文走,告诉你五类walmart最爱产品

在我们跨境圈一直流传着一句话,选品选的好啊,红利吃饱饱。选品的重要性相信不用龙哥多说,选品基本上就是决定了店铺的未来。好的选品不用愁流量、也不用担心走不长久。今天龙哥就来聊聊在walmart上,哪些选品是值得发展的。walmart…

synchronized 加锁 this 和 class 的区别

synchronized 是 Java 语言中处理并发问题的一种常用手段,它也被我们亲切的称之为“Java 内置锁”,由此可见其地位之高。然而 synchronized 却有着多种用法,当它修饰不同对象时,其意义也是不同的,下面我们一起来看。 ​…

实在智能RPA受邀出席2023年东莞市数字赋能峰会,聚力数智制造

3月17日,“数字东莞 科创强市2023年东莞市数字赋能峰会”在松山湖光大We谷圆满举行。本次大会以创新性、专业性、平台化、战略性等为特色,涵盖当今前沿技术、行业痛点、商业模式。会上中国信通院的专家分享了《东莞市数字经济发展报告(2022年…

刷题day40:从中序与后序遍历序列构造二叉树 从前序与中序遍历序列构造二叉树

一、从中序与后序遍历序列构造二叉树 题意描述: 给定两个整数数组 inorder 和 postorder ,其中 inorder 是二叉树的中序遍历, postorder 是同一棵树的后序遍历,请你构造并返回这颗 二叉树 。 需要利用后续遍历(左右中…

java校园报修管理系统ssm

用户的主要功能有: 1.用户注册和登陆登陆系统 2.用户查看报修类型,在线申请报修信息 3.用户对报修信息进行评价 4.用户查看资讯公告信息 5.用户查看个人信息,修改个人信息,修改密码 6.用户在线提交意见反馈信息 7.用户查看报修记录…

记录一次接口套娃数据处理

由于后端接口设计历史遗留问题,要求在一个接口中,通过他返回的数据去请求其他接口,数据以表格的形式渲染出来 目录 前言 一、每次仅展示一个步骤图 二、整合接口数据,一次性渲染 1.请求步骤条接口的地方对数据进行处理 2.修改…

完全小白的pycharm深度学习调试+for循环断点条件设置

完全小白的pycharm深度学习调试for循环断点条件设置写在最前面基础方法pycharm断点调试控制台输入代码中循环的debug方法pycharm中图标的介绍常见的BugDebug经验1. 检查激活函数的输入值2. 检查梯度3. 消融实验4. 使用最短的时间5. 静下心来写在最前面 之前把seq2seqattention…

简单分析Linux内核基础篇——initcall

写过Linux驱动的人都知道module_init宏,因为它声明了一个驱动的入口函数。 除了module_init宏,你会发现在Linux内核中有许多的驱动并没有使用module_init宏来声明入口函数,而是看到了许多诸如以下的声明: static int __init qco…

C++基础算法③——排序算法(选择、冒泡附完整代码)

排序算法 1、选择排序 2、冒泡排序 1、选择排序 基本思想:从头至尾扫描序列,每一趟从待排序元素中找出最小(最大)的一个元素值,然后与第一个元素交换值,接着从剩下的元素中继续这种选择和交换方式,最终得到一个有序…

Redis(十四)【Redisson分布式锁基础介绍】

分布式锁 Redisson 一、Redisson 概述 什么是 Redisson Redisson 是一个在 Redis 的基础上实现的 Java 驻内存数据网格(In-Memory Data Grid)。它不仅提供了一系列的分布式的Java常用对象,还提供了许多分布式服务。 Redisson 的宗旨是促进使…

【数据分析之道①】字符串

文章目录专栏导读1、字符串介绍2、访问字符串中的值3、字符串拼接4、转义字符5、字符串运算符6、字符串格式化7、字符串内置函数专栏导读 ✍ 作者简介:i阿极,CSDN Python领域新星创作者,专注于分享python领域知识。 ✍ 本文录入于《数据分析之…