【Linux网络编程】网络层协议-----IP协议
文章目录
- 一、前置知识:
- 1、引入
- 2、IP = 目标网络+目标主机
- 3、通过编号进行查找:
- 二、IP报头全解析:
- 如何将报头和有效载荷分离:
- 如何将有效载荷交付给上层:
- Socket编程:
- 路由器:
- 三、网段划分:
- 过去的五类IP划分:
- 无类别域间路由(CIDR):
- 特殊的IP地址:
- 私有IP和公网IP:
- ifconfig查看IP:
- 四、补充知识:
- 1、运营商:
- 2、全球网络理解:
- 3、NAT技术:
- 4、路由
- 5、分片与组装:
一、前置知识:
1、引入
首先引入一个故事:
小明数学成绩特别好,有着考满分的能力,这代表什么呢?代表着小明每次考试都有很大的概率考满分,但是是不能够保证每一次都考满分的,但是教务主任很器重小明,只要小明不考满分,都让这次考试重考,那么教务主任+小明就能够保证小明每次考试都考满分
故事中的教务主任就类似于网络中的传输层比如TCP协议,小明就类似于IP协议,IP就有提供将数据跨网络从A主机送到B主机,只要传送失败,都由上层的TCP提供可靠性策略比如超时重传
IP协议的本质工作:提供一种能力,将数据跨网络从A主机送到B主机
用户需要的:提供一种能力,将数据可靠的跨网络从A主机送到B主机
所以:TCP+IP的作用就是将数据可靠的跨网络从A主机送到B主机
2、IP = 目标网络+目标主机
西游记中,在唐僧去西天取经的时候,每当到了一个地方,就和当地的人说:我来自东土大唐,要去西天的大雷音寺取得真经
在上述这句话中有4个加粗的属性,他们在网络中对应的分别是:源IP地址,目的IP地址,目标主机,进程
要对所有主机进行标识,源IP,目的IP来标识源主机和目的主机,这里IP分为私有IP和公有IP,在后面会详细讲讲的
根据上述有:IP并不仅仅是一串数字或者字符串,而是 IP = 目标网络+目标主机
所以:IP为我们在构建网络的时候,为我们将来高速定位一台主机,提供基础保证
在数据传输的过程中,通过IP中的目标网络找到目标主机中所在的局域网,到了之后就能够找到目标主机,然后继续通过端口号找到目标进程,在这个局域网和局域网之间的跳转就是通过路由器进行转发的
3、通过编号进行查找:
我们是活在一个被精心设计过的世界中的,刚出生就有身份证号,在学校中有学号,上班了有工号,这里以学号来举例子:
学号组成一般是有:入学年份+学院编号+专业编号+班级编号+学生编号的
这里为了方便叙述,我们采用学院编号+学生编号
在一所学校中,有许多学院,这里我们将计算机学院的编号为123,所以在计算机学院有一个同学学号就为123006
这个同学捡到了电气学院的学生卡,上面只看得到学号为456007,想要将这个学生卡归还给那个同学有两种方法:
第一种方法:在上课的大楼的门口一个一个的进行问,你是不是这个同学…
这样显然是不行的,因为太浪费时间
归还学生卡的本质是查找对应的人,查找的本质是排除,像上述这种就是线性遍历,一个一个地排除,这样效率太低了
所以就需要效率高的查找方法:
计算机学院的那个同学在计算机的群中@计算机的学生会主席,将这个卡拍给他说我这有张学生卡,当主席看到后,就将学号进行比对,发现456开头是电气学院的,就在学生会主席的群里面@电气学生会主席,所以电气学生会主席就看到了,然后电气
学生会主席就通过后面的学生编号找到对应的人了
为什么效率变快了?------ 因为排除的效率变高了
在上述中,现实对应网络中:一个个学生就是一台台主机,学院的群就是局域网,主席就是路由器,主席之间的群就是公网,学号就是IP
通过进行学号解析,一次淘汰许多不可能在的主机,这样就能够提高查找效率
二、IP报头全解析:
- 4位版本:指的是IP协议的版本,对IPv4就是4,但是如今IPv4已经严重不足了,为了解决问题,有了如下方案:NAT技术,IPv6,其中NAT技术只是减少浪费,并没有增加总量,IPv6就是从根本上解决了问题,增加了IP总量,但是IPv6和IPv4是完全不同的两个协议,是不兼容了
- 4位首部长度:表示IP报头的长度,以4字节为单位,和TCP中的4位首部长度是一样的
- 8位服务类型:由3位优先级(已被弃用),4位TOS字段和1位保留字段,4位TOS字段表示:最小延时、最大吞吐量、最高可靠性、最小成本,这四者相互冲突,只能选择一个
- 16位总长度:IP报文(IP报头+有效载荷)的总长度,无论是字节流还是数据报,所有的报文在IP层其实都是一个一个的数据报,所以,面向字节流的概念,只是TCP层的概念,不是IP层的概念
并且首部长度+16位总长度就是自描述字段 - 8位生存时间(Time To Live,TTL):数据报到达目的地的最大报文跳数,一般是64,每经过一个路由,TTL–,一直减到0还没到达,那么就丢弃了,这个字段主要是用来防止出现路由循环和游离报文
- 8位协议:表示上层协议的类型,是TCP还是UDP
- 16位首部检验和:进行校验,来鉴别数据报的首部是否损坏,但不检验数据部分
- 32位源IP和32位目的IP:表示发送端和接收端所对应的IP地址
如何将报头和有效载荷分离:
固定长度+自描述字段(首部长度+16位总长度):
当IP层得到一个报文后,尽管不知道报文的具体内容,但是知道前20个字节是报头长度,那么就直接读取前20个字节,然后在前20字节中就能够拿到4位首部长度和16位总长度了
通过4位首部长度*4 = 真实报头,因为报头长度起码有20,所以如果大于20就是多出来的选项部分,当读完IP20字节报头和选项后,剩余的就是有效载荷,这样就能够将报头和有效载荷进行分离了
4位二进制的范围是0000 ~ 1111,是0 ~ 15,但是单位是4字节,所以4位二进制能够表示范围是0 ~ 60,又因为报文长度起码有20字节,所以选项最多也就是40字节(更详细可看TCP报文解析)
如何将有效载荷交付给上层:
IP得到一个报文,并进行报头和有效载荷分离后,IP需要知道将有效载荷交给上层的哪一个协议,怎么做到呢?在IP报头中有8位协议字段,这个字段中填充的就是IP需要将有效载荷给上层的哪一个协议,这个填充就是发送端的IP层从传输层得到数据进行填充的,比如上层TCP协议给IP协议数据,此时IP协议进行填充的8位协议字段就是TCP对应的协议编号
Socket编程:
在以前的client连接Server的时候,我们在Linux下是不是 ./client ip port,IP和port用来填充Socket的参数
为什么需要呢?
因为需要这两个来进行目标主机的定位,通过IP给网络层使用,用于数据在网络传输过程中的路由转发,port给对应主机的传输层使用,指明数据应该交给哪一个进程,这就是为什么要将点分十进制ip转化为四字节,因为IP报头的源IP和目的IP是四个字节,所以当一个IP报文扔到网络里面的时候,真正要支持路由的其实是根据我们的32位目的IP地址来进行路径选择的
路由器:
- 路由器本质也是特定子网的主机,也要配置ip地址
- 路由器一定至少要连接2个子网,路由器也就相当于同时在两个子网,所以路由器一定要可以配置多个IP,我们只需要认为路由器有多张网卡即可
- 路由器一般是一个子网中的第一天设备,一般他的IP地址都是网络号为1
- 路由器的功能不仅仅是IP报文的转发,还可以构建子网(局域网)
在我们真正的通信过程之中,中间的路由器是没有TCP层的,只有双方主机是有TCP层的(可以有,但是不需要,因为路由器只工作在网络层)
三、网段划分:
IPv4是32位,那么总共有2^32 = 42亿+,所以IP地址是有限的
过去的五类IP划分:
在早期,将IP地址分为5类
但是这种分法弊端渐渐出现了:
因为A类的网络号比较少,所以A类可申请的网络只有2^7 = 128个
又因为C类的主机号比较少,可申请的主机号只有2^8 = 256个
所以大多数公司都会申请B类IP,这样就会导致B类IP被很快瓜分完了,并且在一个局域网中2^16个主机号也不会全部使用完,并且其他类如A类会造成大量地址的浪费,所以总的来说就造成了大量浪费,比如,申请了一个B类地址,理论上一个子网内能允许6万5千多个主机,A类地址的子网内的主机数更多,然而实际网络架设中,不会存在一个子网内有这么多的情况,因此大量的IP地址都被浪费掉了
无类别域间路由(CIDR):
针对上述的问题,提出了一种新的方案:CIDR
- 引入一个额外的子网掩码来区分网络号和主机号
- 子网掩码也是一个32位的正整数,通常用一串 “0” 来结尾
- 将IP地址和子网掩码进行 “按位与” 操作, 得到的结果就是网络号
- 网络号和主机号的划分与这个IP地址是A类,B类还是C类无关
比如:140.252.20.10 / 24,这就表示前面24位是网络号,后面8位是主机号,倘若这个子网中的子网掩码为255.255.255.0也就是1111 1111 1111 1111 1111 1111 0000 0000
此时就知道子网的范围就是140.252.20.0 ~ 140.252.20.255,但是其中有两个IP地址不用,其中140.252.20.0被称为网络号,140.252.20.255被称为广播
当然倘若将子网掩码改为255.255.255.240 也就是1111 1111 1111 1111 1111 1111 1111 0000,那么如果140.252.20.68在进行运算
最开始是140.252.20.68是IP地址,和子网掩码进行按位与就得到了网络号,然后网络号+1就是可分配的最小IP地址,那么最大IP地址是主机号全1,在这里的主机号是最后4个比特位(这里是4个比特位,怎么算的 ----- 总共是32位,减去子网掩码位数28还剩4位就是主机号的位数)所以范围就是从0100 0000变为0100 1111
子网范围是当前子网下对主机的可分配IP范围
这就是CIDR,这个网络划分方式一定程度上缓解了IP地址不足的问题,但实际上并没有增加IP地址的上线,在这之后,又有了两种解决IP地址不足的问题,分别是动态IP地址分配(想要入网的设备就要先连接家里的路由器,然后路由器就动态分配了一个IP地址,这就是NAT技术),和IPv6
特殊的IP地址:
- 将IP地址中的主机地址全部设为0,就成为了网络号,代表这个局域网
- 将IP地址中的主机地址全部设为1,就成为了广播地址,用于给同一个链路中相互连接的所有主机发送数据包
- 127.*的IP地址用于本机环回测试,通常是127.0.0.1
私有IP和公网IP:
IP地址被硬性划分为私有IP和公网IP
如果一个组织内部组建局域网,IP地址只用于局域网内的通信,而不直接连到Internet上,理论上使用任意的IP地址都可以,但是RFC 1918规定了用于组建局域网的私有IP地址
私有IP:
前8位是10的网络号,10.xxx.xxx.xxx
前12位是172.16 ~ 172.31的网络号,172.16.xxx.xxx ~ 172.31.xxx.xxx
前16位是192.168的网络号,192.168.xxx.xxx
不是私有IP范围的就是公网IP
ifconfig查看IP:
四、补充知识:
1、运营商:
当一家想要入网的时候,那些运营商就会将光纤迁到你家里面,这就是光纤入户,然后在准备调制解调器和路由器就能够实现上网了
将光纤连接到调制解调器,光纤里面的玻璃丝就能够传递光电信号,也就是模拟信号,调制解调器就将这个模拟信号转化为数字信号,再这样就可以被路由器识别了,然后就可以上网了
我们进行上网需要登录密码,连接路由器也需要登录密码,这样就有了上述两个密码,一个给电信,用来验证路由器的正确性,比如说有没有欠费啥的,一套给用户,用来连接局域网
还有一个很重要的叫做:网络基础设施建设,正是因为这些,国家大力发展网络,才能够让全国人民都能够上得起网络,才有更多的互联网公司
为什么要给运营商交钱呢?
- 实际网络通信的基础设施都是运营商搭建的,我们访问服务器的数据并不是直接发送到了对应的服务器,而是需要经过运营商建设的各种基站以及各种路由器,最终数据才能到达对应的服务器
- 因为运营商为我们提供了通信的基础设施,所以我们交网费实际就相当于购买入网许可一样
- 没有运营商提供的这些基础设施,就不会诞生所谓的互联网公司,因为互联网公司是诞生在网络通信基础之上的
也就是说,用户上网的数据首先必须经过运营商的相关网络设备,然后才能发送到互联网公司对应的服务器,因此所谓的网段划分、子网划分等工作实际都是运营商做的
2、全球网络理解:
IP是一份很大的资源,所以就需要对不同的国家进行划分
假如在划分的时候,此时规定前8个比特位作为国家的编号,如下,中国就是0000 0001,美国就是0000 0010,英国就是0000 0011,俄罗斯就是0000 0100
对于国家级别的子网掩码就是255.0.0.0,这样通过IP地址和子网掩码进行按位与,就能够得到国家级别的网路号为1.0.0.0 / 8
所以我们国家的所有网络号都是以1开头的,这是在国际上的划分
接着就是按照一个个省份进行划分,假如我们使用6个比特位进行划分,假如湖北是0000 01,湖南0000 10,江西0000 11,上海0001 00
此时就将前14位都使用了,接着每8位一组进行划分,比如湖北的网络号就是1.4.0.0 / 14,那么对于湖北省里面的所有城市内的IP前面就都是1.4.*了
接着继续进行城市划分,再用4个比特位进行市级的划分,比如将武汉编号为1,荆州编号为2,那么荆州的网络号就是
0000 0001 0000 0100 10 每8位一组进行划分化简就是1.4.128.0 / 18
上述是公网的规则,此时假如一个美国人想访问荆州的一台主机(1.4.128.5),那么首先就将这个IP和国际的子网掩码进行按位与,然后得到1.0.0.0,将这个在国际中进行比对,就知道是中国的,就通过国际路由器跳转到中国局域网,接着喝省级的子网掩码进行按位与得到1.4.0.0,就知道是湖北省的,就通过省级路由器跳转到湖北局域网,然后依次类推直到找到对应主机
3、NAT技术:
像上述那样已经用了18位比特位了,那么还剩下14位,总共也就是16384台主机,那么这已经开始不够用了,并且因为IP地址早期分级,以及后期网民增加,引入了CIDR,再后来又引入了NAT技术
路由器是连接两个或多个网络的硬件设备,在路由器上有两种网络接口,分别是LAN口和WAN口:
LAN口:表示连接本地网络的端口,主要与家庭网络中的交换机、集线器或PC相连
WAN口:表示连接广域网的端口,一般指互联网
我们将LAN口的IP地址叫做LAN口IP,也叫做子网IP,将WAN口的IP地址叫做WAN口IP,也叫做外网IP
像上述那样,我们想要从主机1发送数据到主机2,那么首先通过IP地址+子网掩码判断接收端的主机IP和发送端的主机IP是不是在同一个子网,如果不是,就通过运营商往外发送到了广域网,之后就像我们之前将的全球网络理解那样通过子网掩码逐级定位一步步走到主机2
这里了解一个知识:NAT技术中,对于私网来说,私网的IP是重复使用的,这是为了缓解IP不够用的问题,所以不同的子网可能有相同的私网IP,也就是说可能有无数个子网的网络号是相同的
然后主机2进行处理数据后返回响应,如果返回的是私网的IP,那么是回不去的,因为私网的网络号有许多可能是相同的,所以为了解决这个问题,提出了方案:当私网内主机向公网发送报文时,为了能够让目标主机能够定位回到自己,就要把自己的私有IP替换成当前子网的网关路由器的WAN口IP
如上过程:当主机1发送数据给主机2的时候,有src自己主机1的IP和dst目标IP,首先通过家用路由器,将主机1的IP保存起来,然后将src替换为家用路由器的WAN口IP,之后继续往运营商路由器跳转,到了运营商路由器之后,将家用路由器的WAN口IP保存起来,然后将src替换为运营商路由器的WAN口IP,之后到达主机2并且进行处理完后,将src和dst交换,此时的dst就是运营商路由器的WAN口IP,这样就能够回去了
这个私有IP被不断替换的技术就叫做NAT技术
4、路由
路由是数据问路的过程
我们通过指令route来进行查路由表
其中:
- Destination:目标网络地址
- GateWay:表示下一条地址,如果为0.0.0.0就是代表不需要再路由,即Destination主机与当前设备处于同一子网
- Genmask:表示子子网掩码
- Flags:U标志表示此条目有效(可以禁用某些条目)G标志表示此条目的下一跳地址是某个路由器的地址,没有G标志的条目表示目的网络地址是与本机接口直接相连的网络,不必经路由器转发
- Iface:代表的是发送接口
查路由表的结果:
- 给你具体的下一条
- 路由器不清楚,但是转入默认路由----->同网段的另一台路由器
- 到达入口路由器
因为IP = 目标网络+目标主机
所以我们在进行转发的时候,我们先到目标网络,再在网络中找目标主机
5、分片与组装:
实际上,在一台主机中,报文并没有通过网络层直接发出,而是继续交给下一层协议(数据链路层),对于数据链路层来说,一次不能接收过大的报文,硬性要求上层不能给我交付过大的报文,所以在传输层存在滑动窗口,一个个发,在网络层存在分片,将一个大的报文分成几个小报文进行发送
如下,当查网络的时候,mtu这个就是一次能传输最大数据包的大小为1500字节
当IP层发现这个报文特别大的时候,就需要进行分片,分片后的报文也需要携带新的报头
在之前报头解析的时候,我们有一行没讲,这一行都是关于分片的
- 16位标识:唯一的标识主机发送的报文,如果数据在IP层进行了分片,那么每一个分片对应的id都是相同的
- 3位标志:第二个标志位为0,表示允许分片,第三个标志位表示结束标记(当前是否 是最后一个小包,是的话设置为0。否则的话设置为1)
- 13位片偏移:假如分成了若干片,每一片在原始报文当中的偏移量是什么,这就填充什么
报文如何组装:
这样就进行分片了,当对方收到了这几个分片后的报文,就需要进行组装,首先根据片偏移进行排序,然后就能够保证顺序是对的,就能够组装成功了
细节:
怎么知道收到的当前IP是被分片了的呢?
当收到一个报文,如果片偏移量不是0,那么就证明这是被分片过的,并且不是第一个
那么如果收到第一个呢?也不要紧,此时3位标志中的最后一位就会是1,这样就知道这是分片了的报文,并且这个是第一个
所以 如果片偏移 != 0 或者 更多分片(第三位标志位) == 1就证明当前IP是被分片过的
分片后的报文丢失:
丢报文有三种情况:
- 丢第一个,此时接收方没有收到片偏移量为1的,这样就知道丢失第一个了
- 丢中间,此时在排序的时候,存在一个:后一个偏位偏移 != 前一个偏位偏移+分片大小,此时就能够知道中间存在丢失了
- 丢最后一个,那么就没有收到3位标志中最后一位是0的,这样就知道丢失最后一个了
建不建议分片:
不建议,因为可能增加丢包概率,IP中任何一个分片丢失,在组装的时候都会失败,此时就全部丢弃了,就需要发送方对报文重新发送