IP 层分析

为什么我们使用 UDP 发送会有最大的限制,为什么在 RTP 发送视频码流时会分包为小于 MTU 的包去发送?这一切都要从 IP 层的协议说起。

OSI 七层协议大家都已经非常清楚,其中比较典型的 TCP/IP 协议栈就实现了其中的传输层和网络层,IP (Internet Protocol)协议就是一个网络层的协议,它主要实现了对传输层 (TCP, UDP, RawIp)发送的数据进行分片发送,并决定路由,对收到的 IP 分片进行组帧。然后到下面的链路层。但问题来了,一般链路层都会有自己能承受的最大发送单元(MTU)这个限制,如果是以太网组成的链路,那么 MTU 一般为 1500,也就是说,链路层所承受的载荷最大不能超过 1500,否则发送将失败,也就是整个数据包在链路层,它会认为是由链路层的头部,以太网的为
14(6+6+2)字节的头,加上载荷,而这个载荷不能超过 1500,也就成为网络层,这里我们叫它 IP 层,它的头部加上自己的载荷不能超过 1500,这个 MTU 的限制,所以在 IP 层向链表层封包时,要确保自己的整个数据包不大于 MTU,那么不大于 MTU 的数据到了 IP 层也不用分片,在某种程序上就会使效率提交。

那么这个 MTU 是不是我们使用 UDP 发送时的最大单次发送限制呢?不是,为了让传输层能够使用方便,即使传输层发送的数据大于 MTU 也没有关系,因为 IP 层会对大于 MTU 的数据进行分片,我们来看看 IP 层协议的头信息就知道了。

struct iphdr {
	__u8	version:4,
  		ihl:4;
	__u8	tos;
	__be16	tot_len;
	__be16	id;
	__be16	frag_off;
	__u8	ttl;
	__u8	protocol;
	__sum16	check;
	__be32	saddr;
	__be32	daddr;
	/*The options start here. */
};

我们关注一下几个与本文相关的字段, tot_len是本 IP分片的总长度,包括 IP 头,id 是一个唯一标识,标识相同的 IP 包的不同分片,frag_off 高 13 位表示本分片的 IP 载荷的偏移,它乘以 8 才是真正的字节偏移。 低 3 位表示一个 flag, 分别表示保留位, DF(Don‘t fragment), MF(More fragment)位,DF 位表示不对数据进行分片,MF 位表示,该分片不是最后一个分片,本 IP 包还有更多的分片,所以只有最后一个分片才会清该位。那么这些信息已经足够对一个
IP 包进行拆分和重组了。由于 tot_len 是 2 个字节,所以一个 IP 包最大只能表示 65535 个字节的数据,所以 UDP 最大一次能发送的数据其实应该为 65535 - 20(IP 头大小) - 8(UDP头大小) = 65507 个用户数据。而由于 frag_off 的低 3 位其实是当作标志来使用的,所以标识一个片的偏移只能是 8 的倍数,那么也就意味着上一个分片的数据大小,因为在 IP 层,数据其实是包括传输层头,但不包括 IP 头的,也就是传输层头加上传输层载荷,大小一定是要 8 的倍数,由于最后一个分片后面已经没有分片了,所以它的大小即使不是
8 的倍数也不会影响到后面的偏移。

我们以 ICMP 协议为例,做一个实验。

调用命令 ping -l 2000 172.16.73.92, 也就是带 2000 字节的数据去 ping 172.16.73.92 这台机器。

抓包截图为:

19518 和 19519 这两个数据包为同一个 IP 包的两个分片,是一次 ping 的请求,因为 2000 个用户字节肯定要分为两个 IP 分片,分两个以太网包发出去,上图为 19518 数据包的详细信息,其中 Total Length: 1500 表明本包数据总大小为 1500 包括 IP 头 (20) 和 IP 载荷(包括ICMP 头 8),即该包传送了 1500 - 20 个字节的 IP 载荷,那么下个分片的偏移应该从 1480 开始,Id 为 0xe1f8, MF 标志为 1,表示还有分片,下个包的详细信息为:

该分片 Id 与上个数据包相同,表明是同一个 IP 包,MF 标志为 0,表明是最后一包,偏移就是我们计算得来的 1480,总长度为 548,去除 IP 头,即 528, 第一个包中的 IP 载荷包含了 ICMP 头的 8 个字节,即,第一个包的用户数据为 1500 - 20 - 8 = 1472, 第二个包的用户数据为 548 - 20 = 528, 一共有 2000 用户数据,与理论一致。

协议栈分层的思想非常的清晰,每一层中只关心自己的头部信息与自己的载荷,而该层的载荷其实就是上一层的头部信息和上一层的载荷,每一层不会去关心上一层的头部信息与载荷的情况,这样就使得协议栈条理清晰并且易于扩展。

时间: 2024-10-25 05:57:21

IP 层分析的相关文章

Linux netfilter 学习笔记 之十二 ip层netfilter的NAT模块代码分析

本节主要是分析NAT模块相关的hook函数与target函数,主要是理清NAT模块实现的原理等. 1.NAT相关的hook函数分析 NAT模块主要是在NF_IP_PREROUTING.NF_IP_POSTROUTING.NF_IP_LOCAL_OUT.NF_IP_LOCAL_IN四个节点上进行NAT操作,在上一节中我们知道nat表中只有PREROUTING.POSTROUTING.LOCAL_OUT三条链,而没有NF_IP_LOCAL_IN链,所以不能创建在LOCAL_IN hook点的SNAT

TCP、UDP、IP 协议分析

本文转载自:http://blog.chinaunix.net/uid-26833883-id-3627644.html草根老师博客 互连网早期的时候,主机间的互连使用的是NCP协议.这种协议本身有很多缺陷,如:不能互连不同的主机,不能互连不同的操作系统,没有纠错功能.为了改善这种缺点,大牛弄出了TCP/IP协议.现在几乎所有的操作系统都实现了TCP/IP协议栈. TCP/IP协议栈主要分为四层:应用层.传输层.网络层.数据链路层,每层都有相应的协议,如下图 所谓的协议就是双方进行数据传输的一种

Linux netfilter 学习笔记 之十一 ip层netfilter的NAT模块初始化以及NAT原理

1.NAT的原理 NAT会修改数据包的ip层的源或者目的ip地址.在实际应用中,NAT 主要用于实现私有网络访问公共网络的功能. 1.1 SNAT 源目的地址转换,即对ip数据包的源ip地址进行转换操作,典型的应用即是网关,网关的lan侧会下挂至少两台设备,而这两台设备的ip地址都是lan侧地址,而lan侧设备又要访问公网,这就需要SNAT大展身手了,通过将lan侧发送的ip数据包的源ip地址转换成公网地址即可以访问公网了. 1.2 DNAT 目的地址转换主要是将ip数据包的目的ip地址进行修改

Linux 系统应用编程——网络编程(利用TCP/IP 模型分析数据传输过程)

TCP/IP参考模型是一个非常基础,而且也非常重要的基础框架,要想入门数通这是个必须掌握的基本概念,本文档通过一个简单的示例,结合参考模型来分析一下数通的基本过程. 网络环境非常简单,如下图所示,我们现在来分析一下PC去访问Webserver的WEB服务,整个数据通信过程是如何发生的,为了简化描述,我们这里暂时忽略DNS.ARP.帧校验等等机制的工作细节,只考虑较为宏观的层面. 1)PC访问WebServer的WEB服务,实际上是访问Webserver的HTTP服务.这个过程对于人来说,就是在P

TCP/IP协议分析(推荐)

一;前言 学习过TCP/IP协议的人多有一种感觉,这东西太抽象了,没有什么数据实例,看完不久就忘了.本文将介绍一种直观的学习方法,利用协议分析工具学习TCP/IP,在学习的过程中能直观的看到数据的具体传输过程. 为了初学者更容易理解,本文将搭建一个最简单的网络环境,不包含子网. 二.试验环境 1.网络环境  如图1所示 图1 为了表述方便,下文中208号机即指地址为192.168.113.208的计算机,1号机指地址为192.168.113.1的计算机. 2.操作系统 两台机器都为Windows

【转】TCP/IP ECN分析

转自http://blog.sina.com.cn/s/blog_6cf9802d0100xtwv.html 一. 现有TCP流量在拥塞的情况下出现的问题 根据RFC793的描述,TCP协议是按照端到端设计的可靠的流传送协议.其特点是: 1. 在三次握手建立连接时,协商发送端和接收端的发送和接收能力,滑窗. 2. 在完成连接建立之后,TCP按照当初协商的窗口大小进行报文的发送. 3. 提供可靠地连接,TCP的接收端将使用ACK机制通知发送端数据是否成功接收. 4. TCP发送端按照接收端的ACK

第二十二章 TCP/IP层的实现

                      第二十二章    TCP/IP层的实现        我比较喜欢先难后易,如果把GPU显示管理.和网络管理拿下后:我会从头整理.改写一遍APO操作系统.这样,就会形成APO操作系统的锥形.也获得了全局观.内核CPU线路.和用户CPU线路,你可以将它们看成是独立的2个32位CPU核:内核CPU主要任务是实时处理.硬件中断,256个实时线程包含了一些中断程序的后半部.用户CPU主要是动态优先级进程.线程调度,各种应用程序的运行:2个核之间是通过消息交互.句

android telephone 4.2 framework层分析

framework层的相关代码主要在GSMPhone.CallManager.GSMCallTracker.TelePhonyManager中. GSMPhone: 与GSMPhone关联的主要是Phone.java.PhoneBase.java.GSMPhone.java.Phone作为基类,定义了25对Handler消息注册和注销的接口,而PhoneBase继承Phone实现了24对,还有一对在GSMPhone中实现,而GSMPhone继承了PhoneBase. 如何管理Phone对象的呢?

Why 使用TLS记录协议封装IP层VPN IS A Bad Idea

一个很自然的想法,使用TLS封装一个IP数据报实现一个第三层的VPN.这种想法一定是经过了深思熟虑的,但是不幸的是,这是个错误的想法.有一篇文章<Why TCP Over TCP Is A Bad Idea>,详细解释了Why.事实上重传叠加问题是无法解决的,要知道,TCP的RTO计算是极其复杂的,影响它的因素也很多,这就是说,只要你用一个TCP封装另一个TCP,外层TCP丢包,且RTO小于内层TCP的RTO,连接就会崩溃.而以上这个条件是很容易满足的.       用TLS来封装IP数据报是