🔥个人主页: Milestone-里程碑
❄️个人专栏: <<力扣hot100>> <<C++>><<Linux>>
🌟心向往之行必能至
目录
一.IP协议
[1.1 IP协议的核心作用和构成](#1.1 IP协议的核心作用和构成)
[1.2 ip协议的报头](#1.2 ip协议的报头)
[1.3 网络划分(重点)](#1.3 网络划分(重点))
[1.3.1 为什么要子网划分](#1.3.1 为什么要子网划分)
[1.3.2 设置IP](#1.3.2 设置IP)
[1.3.2.1 解决IP不足](#1.3.2.1 解决IP不足)
[1.3.2.2 特殊的IP地址](#1.3.2.2 特殊的IP地址)
[1.4 IP地址的数量限制](#1.4 IP地址的数量限制)
1.4.1解决办法:私有IP和公有IP
[1.4.1.1 引入例子,加强理解](#1.4.1.1 引入例子,加强理解)
[1.4.1.2 再引入例子,更加详细,从市的局域网与公网](#1.4.1.2 再引入例子,更加详细,从市的局域网与公网)
1.4.1.3网络拓扑
[1.4.1.4 查看主机配置的IP](#1.4.1.4 查看主机配置的IP)
[1.5 报文分片](#1.5 报文分片)
[1.5.1 学习分片和组装](#1.5.1 学习分片和组装)
[1.5.2 细讲补充](#1.5.2 细讲补充)
一.IP协议
基本概念
主机: 配有IP地址, 也要进⾏路由控制的设备;
路由器: 即配有IP地址, ⼜能进⾏路由控制;(工作在网络层,但现在的路由器,应用层也可工作)
节点: 主机和路由器的统称
1.1 IP协议的核心作用和构成
IP协议:提供一种能力看,将数据报从A主机,跨网络,送到B主机
理解网络层和传输层
在数据传输过程中,网络层的IP有能力将数据传输成功
但有能力不代表一定能,此时就需要与传输层的TCP合作
这样,TCP/IP协议,才能把数据百分百可靠的,从A主机跨网络送到B主机
1.2 ip协议的报头
首先,我们要明确,IP协议的报头为固定长度,20字节,但这里4位头部长度,也才15啊,其实与TCP一样,基本单位是4个字节
0,15\]-\>4字节 \[0,60\] 然后 20/4-\>5-\>4+1-\>0100+0001-\>0101

> 8位服务类型
> 8位服务类型(Type Of Service): 3位优先权字段(已经弃⽤), 4位TOS字段, 和1位保留字段(必须置 为0). 4位TOS分别表⽰: 最⼩延时, 最⼤吞吐量, 最⾼可靠性, 最⼩成本. 这四者相互冲突, 只能选择 ⼀个. 对于ssh/telnet这样的应⽤程序, 最⼩延时⽐较重要; 对于ftp这样的程序, 最⼤吞吐量⽐较重要.
> 8位⽣存时间(
> Time To Live, TTL): 数据报到达⽬的地的最⼤报⽂跳数. ⼀般是64. 每次经过⼀个路
> 由, TTL -= 1, ⼀直减到0还没到达, 那么就丢弃了. 这个字段主要是⽤来防⽌出现路由循环
> 如:
> 有时会出现报条一直在内部循环转发
> 
> 16位首部检验和,使⽤CRC进⾏校验, 来鉴别头部是否损坏
>
> 与TCP所讲一样,是防止比特位翻转的
struct iphdr {
#if defined(__LITTLE_ENDIAN_BITFIELD)
__u8 ihl:4,
version:4;
#elif defined(__BIG_ENDIAN_BITFIELD)
__u8 version:4,
ihl:4;
#else
#error "Please fix "
#endif
__u8 tos;
__be16 tot_len;
__be16 id;
__be16 frag_off;
__u8 ttl;
__u8 protocol;
__sum16 check;
__be32 saddr;
__be32 daddr;
/*The options start here. */
};
> 4位版本号(version):
> 指定IP协议的版本, 对于IPv4来说, 就是4
> • 8位协议: 表⽰上层协议的类型
> • 32位源地址和32位⽬标地址: 表⽰发送端和接收端.
> 16位总⻓度(total length): IP数据报整体占多少个字节.
> 4位版本号(version): 指定IP协议的版本, 对于IPv4来说, 就是4
剩余的报头组成,在后续详细讲解
### 1.3 网络划分(重点)
IP地址分为两个部分, ⽹络号和主机号
• ⽹络号: 保证相互连接的两个⽹段具有不同的标识;
• 主机号: 同⼀⽹段内, 主机之间具有相同的⽹络号, 但是必须有不同的主机号
*** ** * ** ***
先建立共识,为什么我们发消息能够精准发送,本质上是网络本身是发展几十年的产物,与此同时,网络建设也是发展了几十年的(国内运营商建立基站,拉网线等)---网站是被设计的
引入例子加强理解,一所大学里,假设都分好了学院,而我们假设学号是:院号+专业+班级+学号
就如我们下面这张图,其中学院内的学生,除了该学院的学生会主席与其他院的学生会主席建立了校群,有向外通信的能力,其他的学生,都只能在自己这个院的局域网通信(此处我们简化了,其实应该还要班级等等联络人)

假设某天下雨,学号为01123的张三捡到了一个钱包,里面有许多贵重物品和一张学生卡(由于雨水,只能看到学号:03333)
而张三为了将这个钱包物归原主,可以在大学里一个一个地找,但效率太低,因此就应该通信
张三看学院号为03333,非自己学院号的01,自己不认识,不会通信,此时就采用了缺省值,交给院学生会主席01110,同时带上源IP地址(学号:01123)和目的IP地址(03333),而主席看到后,发现是材料学院的,就将这个转发1给材料学院的学生会主席,材料学院的学生会主席看到后,将带有目的IP和源IP和数据:钱包就交给了目的IP的人
*** ** * ** ***
与我们说过网络是被建设的,同样的,在我们没有上大学的时候,上面的学院也有了---\>被学校已经建设好了(划分学院,带上唯一编号的过程:子网划分)
#### 1.3.1 为什么要子网划分
未来查找目标主机,必须先查找目标网络
本质:
> 本质是淘汰其他网络,可以在全网中提高查找目标主机的效率
>
> 在上面的学校例子中,张三淘汰了自己学院的学生,院学生会主席淘汰了除材料学院的学生,材料的学生会主席淘汰了院内除目的学生的学生
>
同时,二分查找也是通过不断淘汰,提高效率
*** ** * ** ***
• 不同的⼦⽹其实就是把⽹络号相同的主机放到⼀起.
• 如果在⼦⽹中新增⼀台主机, 则这台主机的⽹络号和这个⼦⽹的⽹络号⼀致, 但是主机号必须不能
和⼦⽹中的其他主机重复.
如下面的主机A/B/C等都有网络标识,那么哪里来的呢?
其实是我们连网时,向路由器请求,路由器自动分配(DHCP)(断网可能会回收)

而我们的路由器,既要与内部设备通信,又要与外部通信,因此至少需要配置有两套IP
#### 1.3.2 设置IP
IP是有限的,被各个国家的运营商抢占
为何要抢?构建自己的子网
⼿动管理⼦⽹内的IP, 是⼀个相当⿇烦的事情.
• 有⼀种技术叫做DHCP, 能够⾃动的给⼦⽹内新增主机节点分配IP地址, 避免了⼿动管理IP的不便.
• ⼀般的路由器都带有DHCP功能. 因此路由器也可以看做⼀个DHCP服务器.
> IP=网络号+主机号
> 子网划分的本质:把32位比特位进行划分,确定有多少网络号
*** ** * ** ***
过去曾经提出⼀种划分⽹络号和主机号的⽅案, 把所有IP 地址分为五类(IPV4)

> • 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地址都被浪费掉了
##### 1.3.2.1 解决IP不足
针对这种情况提出了新的划分⽅案, 称为CIDR(Classless Interdomain Routing)(⽆类别域间路由):
• 引⼊⼀个额外的⼦⽹掩码(subnet mask)来区分⽹络号和主机号;
• ⼦⽹掩码也是⼀个32位的正整数. 通常⽤⼀串 "0" 来结尾;
• 将IP地址和⼦⽹掩码进⾏ "按位与" 操作, 得到的结果就是⽹络号;
• ⽹络号和主机号的划分与这个IP地址是A类、B类还是C类⽆关;
*** ** * ** ***
举两个例子
子网掩码,即将IP与子网掩码进行\&

通过子网掩码 的设置,原来68这部分的0100 0000+ 0100 = 0100 0100全变为了0
因此,子网存在的意义就是通过设置1的个数,重新设计网络号,使IP资源得到充分利用
上面这个 140.252.20.68/24后,子网地址范围,即这个子网最多连多少台主机
为256-1(子网后的为全0,表示局域网)-1(子网后全为1,表示广播地址(后续讲))
> 如果觉得上面的划分还是有点浪费,那么可以尝试下面的

上面的这个子网最多连14台主机
##### 1.3.2.2 特殊的IP地址
• 将IP地址中的主机地址全部设为0, 就成为了⽹络号, 代表这个局域⽹;
• 将IP地址中的主机地址全部设为1, 就成为了⼴播地址, ⽤于给同⼀个链路中相互连接的所有主机发 送数据包;
• 1 27.\*的IP地址⽤于本机环回(loop back)测试,通常是127.0.0.1
### 1.4 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还没有普及;
##### 1.4.1解决办法:私有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);
> 网络宏观上被划分为:
>
> 公网:内网(子网,局域网)=1:n
>
> 但需要注意的是,我们普通人接入的都是内网,并且在网络通信的过程中,私有IP不可以出现在公网
*** ** * ** ***
###### 1.4.1.1 引入例子,加强理解

假设上面刚开始发的

而发送主机发现122.开头的不在自己的局域网内,无法直接通信,于是就缺省路由,将它 转发给路由器,而路由器发现dst也不是自己所在的局域网,所以再缺省路由,发给他对应的路由器,同时通过NAT,将src地址匾额我i自己的QAN口IP

而接受到的路由器,发现122.\*与自己处在同一个网络内,可以直接通信,因此直接进行发送,并将src替换为自己的WAIN口

目的路由器接受到后,再根据后续的主机地址发送给目的地,处理完再返回,而由于有公网的src IP,所以一定能返回路径的倒数第一个经过点,但返回到后,src与自己的WAIN口ip一样了,无法进行访问了,怎么办?
> 其实与前面使用NAT替换一样,会进行处理,此处后面详解
*** ** * ** ***
上面的过程中,我们发现堆src ip要一步一步进行替换,最多会替换到公网IP再完成任务后反向替换
试问: 如果 私有IP可以出现在公网上,那么我们局部的通信设备访问公网资源可以访问,但给我们返回应答时,该怎么处理? (私有IP只在子网为1,但如果我们不同的子网,相同的私有ip直接出现在公网,返回就不知返回给谁了)
**欠费,敏感信息**
如果我们绑定路由器的手机号欠费了,我们会发现自己无法使用wifi了,其实是我们发送的报文里,携带了话费余额,运营商看到欠费后,就不帮我们转发了
我们访问国外网站或者其他敏感信息的时候,会发现无法访问, 其实就是运营商检测到有敏感信息,不帮我们转发
公网的理解
每个国家都有公网IP进行组建自己的内网,而公网IP的多少,则是看网民的数量
*** ** * ** ***
小总结
> 1.上面通过NAT技术及私有IP不可出现在公网,就解决了IP地址不足的问题
>
> 2.每经过一个内网路由器,进行srcip的时候,替换成为当前路由器的wan口ip,(对外的)
>
> 3.上面的例子,我们也可以感受到,每个路由器,至少要配套两个IP
###### 1.4.1.2 再引入例子,更加详细,从市的局域网与公网


一,国外俄罗斯的地址访问5.1.16.X,发给中国,一层一层替换src
而对应那些大公司,我们就可以将它们想像与市的服务器同级,而大厂的服务器一般在多个区域都会有部署
*** ** * ** ***
###### 1.4.1.3网络拓扑
网络拓扑的结构非常复杂,这里我们把上面的"市",替换成为各个互联网公司,那么内网环境就是公司内网
###### 1.4.1.4 查看主机配置的IP
linux : route

此时我们看到的default对应的ip就是缺省ip,当源地址要访问的ip在路由器未配置时,就转发给该ip
下面是两个例子

### 1.5 报文分片

我们前面的博客,可以看见,对应一个4000大小的滑动窗口还进行了分区,每个区的大小为1000,原因就是数据链路层的设定(后续详细讲解)
数据链路层:从上层接受下来的完整报文,大小不超过MTU,最大传送单元,一般是1500字节(但数据是1460字节,因为ip和tcp报头还要各占40字节),为什么?
并且数据链路层只通知,不分片,分片由你网络层完成,同样的,组装也由对端的网络层完成
举个例子,加强理解
> 你有1台10公斤的电脑,打算寄快递发给你的朋友,但快递公司说,他们最多一个快递寄3公斤,你为了寄出,只能进行拆分 分片,同样的,组装也是由你朋友收到快递后进行组装
*** ** * ** ***
结论一:网络通信的过程,如果过多分片,就会导致丢包率
但分片和组装不是主流,要减少,而主要收传输层传输有关
#### 1.5.1 学习分片和组装

分片与组装主要用到上面表格中的第二行
> • 16位标识(id): 唯⼀的标识主机发送的报⽂. 如果IP报⽂在数据链路层被分⽚了, 那么每⼀个⽚⾥⾯的这个id都是相同的. (不同报文,标识不同,相同报文,标识相同)
> • 3位标志字段: 第⼀位保留(保留的意思是现在不⽤, 但是还没想好说不定以后要⽤到). 第⼆位置为1 表⽰禁⽌分⽚, 这时候如果报⽂⻓度超过MTU, IP模块就会丢弃报⽂. 第三位表⽰"更多分⽚", 如果 分⽚了的话, 最后⼀个分⽚置为0, 其他是1. 类似于⼀个结束标记.
> • 13位分⽚偏移(framegament offset): 是分⽚相对于原始IP报⽂开始处的偏移. 其实就是在表⽰当 前分⽚在原报⽂中处在哪个位置. 实际偏移的字节数是这个值 8 得到的. 因此, 除了最后⼀个报⽂之外, 其他报⽂的⻓度必须是8的整数倍(否则报⽂就不连续了).
*** ** * ** ***
1. 如何确定特定报文是否被分片?
> 1.更多分片是否是1,如果是1,就是分片
>
> 2.更多分片是否为0,如果是0且13位偏移量不为0,那就是分片
2.怎么确保自己把分片收全了
> a.相同的标识的分片,聚合在一起!
>
> b.怎么保证你收全了?
反过来想,怎么确定没有收全?
1.第一片丢失 即一个标识符的切片,没有偏移量为0的切片
2,中间片丢失
> 把收到的所有分片,按照片偏移量进行升序排序!
>
> 片偏移+自身报文的长度=下一个分片的片偏移数字
3. 结尾丢失 没有更多分片为0的
所有组装则是与分片相反,不再赘述
*** ** * ** ***
#### 1.5.2 细讲补充
> 1.如何尽可能确保不会分片?
>
> 在三次握手时,两端就会交换各自的数据链路层的MTU,进行比较,以最小的为上限
>
> 2.在网络转发的过程中,可能会遇到MTU更小的,此时就会再进行分片