C/C++ Linux网络编程15 - 网络层IP协议

上篇文章:C/C++ Linux网络编程14 - 传输层TCP协议详解(保证可靠传输)-CSDN博客

代码仓库:橘子真甜 (yzc-YZC) - Gitee.com

应用层解决具体应用的问题,传输层解决的是两个网络进程之间数据通信以及如何通信的问题(是否需要连接?是否需要可靠传输?是否需要报文?)。

而网络层主要解决的是数据包如何从一个主机发送到另一个主机,包含 路径选择,寻址,转发,网络拥塞控制等功能。

目录

[一. IP基本概念](#一. IP基本概念)

[二. IP报头格式](#二. IP报头格式)

[2.1 4位首部长和16位总长度](#2.1 4位首部长和16位总长度)

[2.2 8位协议与16位检验和](#2.2 8位协议与16位检验和)

[2.3 生存时间与源ip目的ip](#2.3 生存时间与源ip目的ip)

[2.4 版本号](#2.4 版本号)

[2.5 标识/片偏移和标志](#2.5 标识/片偏移和标志)

[三. 网段划分](#三. 网段划分)

[3.1 子网划分](#3.1 子网划分)

[3.2 特殊IP地址与IP数量限制](#3.2 特殊IP地址与IP数量限制)

[3.3 私有IP和公有IP](#3.3 私有IP和公有IP)

[四. 路由器和路由](#四. 路由器和路由)

[4.1 路由器](#4.1 路由器)

[4.2 路由](#4.2 路由)

[五. IP分片与组装](#五. IP分片与组装)

[5.1 IP报文为何需要分片?](#5.1 IP报文为何需要分片?)

[5.2 如何进行分片和组装](#5.2 如何进行分片和组装)

[5.3 分片的意义](#5.3 分片的意义)


一. IP基本概念

IP是用于定位和标识一个主机的位置的,用于跨主机将数据传输到目的主机。 有了对方IP我们才能再网络中进行路径选择。IP就是主机在网络上的逻辑地址

IP层收到上层(传输层)的数据后,会封装一个IP报头再交付给数据链路层。IP收到下层(数据链路层)的数据后会解析出IP报头,然后将其交付给的传输层。

二. IP报头格式

传输层的TCP/UDP有自己的报头,网络层也是如此。IPV4报头格式如下:

可以看到IP的固定首部长度是:(32 * 5) / 8 = 20 字节

2.1 4位首部长和16位总长度

4位首部长:用于计算IP报头的长度,计算方式是4位首部长 * 4。 由于固定长度是20字节,所以首部长最小值是 20/4 = 5 即 0101。同理也能获取最大值 (1111) * 4 = 15 * 4 = 60字节

16位总长度:用于表示整个IP报文的长度,16位总长度 - 4位首部长 = IP有效载荷的长度。

我们知道:TCP报头中并没有一个字段表示TCP报文长度,一般使用IP的有效载荷长度来表示TCP报文的长度

2.2 8位协议与16位检验和

8位协议:用于表示交付给上层的是何种协议,比如UDP/TCP。

16位检验和:用于检测IP报文有没有损坏(数据错误或者字节数多了/少了),如果发现错误就会丢失这个IP报文

可以看到,IP层并不保证可靠性(如果上层是TCP的话,这个报文就会被重传,如果是UDP的话,报文丢失了也没事,符合UDP特性)

2.3 生存时间与源ip目的ip

8位生存时间:网络传输中,我们无法保证一个IP报文能够被对方接收,为了避免IP报文长时间无法到达对方(比如进入了环路永远无法到达地方)从而导致网络阻塞。设置了一个生存时间TTL,每当IP报文被传输到下一跳,TTL就会-1。当TTL = 0时候,这个报文就会被丢弃。

源ip和目的ip:用于标识该报文的发送方IP和接收方IP,方便寻址和每一个节点转发报文

2.4 版本号

用于标识使用的协议是IPV4还是IPV6,由于IPV4的格式只有32位,最多表示2^32 - 1 的主机。也就是4294967295,42亿个IP地址。可是目前全球人类有80多亿,一个也不可能只有一台主机。所以IPV4提供的IP地址是明显不够的

而新提出的IPV6是128位,最多提供2^128 - 1 个IP地址,远大于80亿。

这里给出IPV6的报文格式,但不过多赘述。

2.5 标识/片偏移和标志

用于IP的分片和组装,后续会详细说明

三. 网段划分

3.1 子网划分

什么是子网划分?

网段划分就类似于学校中的学号划分 2022(年份) 1100(学院/专业) 05(班级) 38(班级编号)

为什么要子网划分?

我们的IP也是一样,互联网中的每一台主机,都必须要位于某一个子网。可以通过子网定位这一台主机,通过你属于哪一个子网,可以排除大量其他IP地址。

如何进行子网划分,谁来做这个工作?

IP地址有32位,子网划分是运营商划分的(联通,电信,移动)

网络号:保证相互连接的两个网段具有不同的标识

主机号:表示同一个网络中,不同的主机具有相同的网络号,但是具有不同的网络号

路由器属于不同的网段,所以路由器具有不同的ip地址,通常是网段子网号.1

每一个子网中新增一台主机,这台主机的网络号必须与子网的网络号相同。那么这些子网内的ip地址是不是需要管理呢?

子网内的ip地址的管理是由内部的DHCP完成的

由于A类B类C类这样划分子网会导致浪费大量的IP地址,引入了一个子网掩码概念

网络号 = ip地址 & 子网掩码

目标网络和子网掩码,子网中的主机,都会由路由器管理

3.2 特殊IP地址与IP数量限制

0.0.0.0表示局域网,1.1.1.1表示广播地址。127.0.0.1表示本地回环地址

为了解决IP地址的数量限制,目前有下面这些技术:

1 动态分配IP地址(DHCP),只给接入网络的主机分配IP,不接入网络只有MAC地址。这样就能缓解IP数量限制,不过这样一台主机可能会有多个不同的IP地址

2 NAT技术:将网络分为内网和公网,通过内网IP->公网IP来缓解IP数量限制

3 IPV6:拥有2^128-1个IP地址,是解决IPV4地址不够的终极方案。不过目前全球还没有完全推广

3.3 私有IP和公有IP

如果一个局域网内部组织网络,IP地址只用于局域网内中通信。理论上来说,可以随意使用任意的IP地址。但是官方规定了:

以10*开头的

172.16 到 172.31

192 168 *

只能用上面的三类IP地址来建立私有IP,其他的都是公网IP。

我们访问服务器,必须要通过运营商的路由,然后访问目的IP地址。所以 翻墙翻的就是绕过运营商访问外网IP

四. 路由器和路由

4.1 路由器

路由器是用于路由(转发),NAT(内网与公网转换),DHCP(动态分配IP地址)的装置。可以用于组建局域网,不过组建的时候只能使用内网IP。

路由器一般有两个IP,分别为LAN口IP和WAN口IP。LAN口IP是子网IP,用于对内的,WAN口IP是用于对外的

子网中的主机想要对外通信,路由器需要将IP首部的IP地址替换为WAN口IP,然后逐级替换,最后数据包中的IP地址就是公网IP。这种技术就是NAT技术

4.2 路由

主机向其他主机发送数据时候:

1 不知道目的IP在哪,也不知道路由器在哪:这种情况直接将数据发送给默认路由器进行路由

2 不知道目的IP在哪,但是知道某一个路由器A知道:将数据发送给路由器A

3 知道目的IP在哪,说明目的IP就在我的子网中:直接将数据发送给对应主机

我们使用route命令,即可查看路由表:

五. IP分片与组装

5.1 IP报文为何需要分片?

IP报文的最长长度是 2^16 -1 = 65535字节。IP的有效载荷最长长度是 65535 - 20 - 65515字节。相对的:TCP报文有效载荷最长是65535 - 20 - 20 = 65495字节,UDP最长有效载荷是65535 - 20 - 8 = 65,507字节。

虽然你们都很长,但是数据链路层却规定了自己的MAC协议帧,明确表示一个帧的有效载荷不可超过1500字节(MTU单元)。

这就表示,IP报文(报头+有效载荷)不可超过1500字节。

不过实际上,IP报文的长度不并由IP网络层决定。而是由传输层TCP/UDP决定,如果传输层发送了一个数据报长度是6666字节,IP层该怎么办?

之前提到的标识/片偏移和标志就是用于实现IP分片和组装的。

分片:当TCP/UDP报文长度超过1500字节时候就需要分片,由自己完成

组装:由对方主机的IP层完成。

传输层:TCP/UDP不关心IP是否分片,只关心自己有没有收到一个完整的报文

数据链路层:MAC帧不关心自己是否分片,只关心自己MAC帧传输到下一个主机

5.2 如何进行分片和组装

1 同一个报文的不同分片如何区分,比如首个分片,中间分片,最后分片?

标志和片偏移:用于标记某一个ip是否分片 标识:标识相同的ip报文分片,属于同一个IP数据报

没有分片:标志MF和片偏移Offset都为0

如果分片:

首个分片:标志MF是1,片偏移Offset是0

中间分片:标志MF是1,片偏移Offset > 0

最后分片:标志MF是0,片偏移Offset > 0

2 如何保证识别报文的先后顺序?

接收方通过标识将相同的ip分片组合在一起,通过片偏移来排序这些ip分片

3 如果由ip分片丢失了呢?如何解决

使用当前分片的起始地址 + 当前分片长度找到写下一关分片的片偏移,当发现不对之后这个ip数据报就会丢弃。然后UDP直接丢弃报文,TCP会重传

4 如何确定组装的IP数据报是正确的?

如果经过IP检验/TCP检验和/UDP检验和,都没有出错。该报文就是正常的,如果出错了就根据不同协议的规定处理即可

16位标识:如果IP报文因为MTU分片了,相同报文的每一个分片的标识位是相同的

3位标志:第一1暂时不用,第二个标志位标识静止分片(为1的话,如果报文过大直接丢弃该报文)。第三标志位表示"更多分片",为1表示该分片后面还有分片,为0代表该分片是该报文的最后一个分片(即分片了的报文最后一个这位是0,其他分片是1)

13位分片片偏移:表示这个分片的是相对于原始IP数据报开始处的偏移量。即表示分片在原始报文的位置

5.3 分片的意义

分片是为了数据链路层更好的传输数据,通过分片我们虽然能保证数据有效传输,但是也会带来更多的操作和错误。(比如分片,组装需要时间,一个分片出错整个报文就丢失了)

所以我们正常写代码的情况下,能够减少TCP/UDP报文长度的情况下,尽量控制报文长度为1500字节以下,减少IP分片,提高通信效率

相关推荐
云老大TG:@yunlaoda3602 小时前
华为云国际站代理商IMS主要有什么作用呢?
tcp/ip·华为云·云计算·负载均衡
Allen正心正念20252 小时前
网络编程与通讯协议综合解析
网络
bing_feilong2 小时前
ubuntu中的WIFI与自身热点切换
网络
拾贰_C3 小时前
【Linux | Windows | Terminal Command】 Linux---grep | Windows--- findstr
linux·运维·服务器
CodeByV3 小时前
【网络】UDP 协议深度解析:从五元组标识到缓冲区
网络·网络协议·udp
车载测试工程师3 小时前
CAPL学习-AVB交互层-概述
网络协议·tcp/ip·以太网·capl·canoe
asiwxy3 小时前
OpenGL 材质
c++
阿华hhh3 小时前
Linux系统编程(标准io)
linux·开发语言·c++
虹科网络安全4 小时前
艾体宝洞察 | 利用“隐形字符”的钓鱼邮件:传统防御为何失效,AI安全意识培训如何补上最后一道防线
运维·网络·安全