IP协议原理(2)

IP地址的数量限制

我们知道, IP地址(IPv4)是一个4字节32位的正整数. 那么一共只有 2的32次方个IP地址, 大概是43亿左右. 而TCP/IP 协议规定, 每个主机都需要有一个IP地址. 这意味着, 一共只有43亿台主机能接入网络么?

实际上, 由于一些特殊的IP地址的存在, 数量远不足43亿

==例如我们上面说的127*,还有一些ip地址是专门用来构建局域网的,还有的ip不是给正常的主机使用的!而是给网络中的中间节点使用的!==

另外IP地址并非是按照主机台数来配置的, 而是每一个网卡都需要配置一个或多个IP地址.

CIDR在一定程度上缓解了IP地址不够用的问题(提高了利用率, 减少了浪费, 但是IP地址的绝对上限并没有增加), 仍然 不是很够用. 这时候有三种方式来解决

==动态分配IP地址: 只给接入网络的设备分配IP地址. 因此同一个MAC地址的设备, 每次接入互联网中, 得到 的IP地址不一定是相同的;==

就像是当我们手机还没有连接wife或者打开热点的时候!我们就会发现我们手机里面没有ip地址!

==NAT技术==

==IPv6: IPv6并不是IPv4的简单升级版. 这是互不相干的两个协议, 彼此并不兼容; IPv6用16字节128位来表 示一个IP地址; 但是目前IPv6还没有普及==

私有IP地址和公网IP地址

我们上面说过有些IP只能在私网使用!有些只能在公网使用!那么写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);

只能在这三类构成局域网!

==我们常说IP地址具有唯一性指的是全局IP(公网IP)==

image-20231101200604334

==那么公网和私网的关系究竟是什么呢?首先我们要了解什么是运营商!==

在一个没有通往的偏远地区!我们自己家里没有网,**但是附近的邻居已经通网了!**我们如果想给自己的家里通网!那么我们应该如何给家里通网线呢?

在偏远地区如果想要入网!首先我们就得给家乡附近的运营商打电话,比如说:电信,联通,移动,我们假设给电信打电话,随后电信的工作人员就会上面!

工作人员会带很多的光纤,网线,调试解调器(猫),路由器等设备! 因为我们邻居也已经通网了,所以附近会有一些入网的接口,随后工作人员会从外部的哪里拉一根网线拉到我们家里!

然后装上猫和路由器,配置好,现在运营商还会送一张电话卡,卡里面有很多流量!然后会要求我们往电话卡里面充后

这个电话卡就是我们家里面的入网的账号!还能给账号设一个密码

当我们冲完钱后,工作人员就将手机号和密码,配置进路由器里面!因为我们电话卡已经交过费了,路由器配置好后,网络就连通了!

最后还会给这个路由器配一个无线账号和无线密码,然后我们就可以通过手机/笔记本连通这个wife了!就可以上网的!

首先工作人员的网线哪里拉的?——肯定是运营商将网络基础设施建到了我们的村子里面!(一般城市里,建房子的时候,就已经统一留了网口!所以就不用拉的,农村里面就要一个个的跑)

==上面我们的故事里面!运营商扮演了举足轻重的地位!当我们上完的时候,我们的路由器会发起请求,会携带家里配置的路由器账号密码信息(不是无限账号),然后先到运营商的机房里面!(交换集群,转发基站)然后对我们的账号进行认证!发现没有欠费!然后就放我们的报文过去!(如果欠费就不让报文过去)——运营商的角色就是一个收过路费的角色!==

就好比我们村子和旁边的超市之间隔了一条河,大家过不去!这时候来了一群人修了一座前!这样大家都能过去了!但是每次过去都要求要1块钱才能过去!然后才能回来

我们在上网的时候其实不是直接给这些为我们提供服务的公司交钱,但是一定要向运营商交钱!因为运营商卡在我们和那些提供服务公司中间的基础设施建设者!

同样的那些公司想要将他们的服务提供给我们消费者也是要经过运营商!让运营商给他们拉网线!运营商也要收他们的过路费!

==这也是为什么我们一旦手机欠费,刷不了抖音,用不了qq,打不了电话!但是却可以打运营商的电话(例如10086)这是因为,运营商虽然拦截下来了我们的数据不进行转发!但是没有拒绝我们发数据给它们!==

运营商,也可以对我们的数据进行审核!当发现我们要访问外网的IP的时候例如谷歌!可以丢弃我们发送的报文!不进行转发!

我们经常说的"墙",就是存在于运营商的转发逻辑当中!

那么我们能不能绕过运营商直接访问,qq,微信等软件呢?——不行!物理上就完全不可以,因为物理上我们的和字节,腾讯的主机是压根没有连接的!物理上我们就必须走运营商的设备!

==上面我们说了那么多!我们还发现路由器这个设备不是看着那么简单!可以做很多事情==

1.转发功能

2.DHCP|组建局域网的功能

3.还有NAT功能!

组建的局域网功能体现在哪里呢?

体现在营运商的工作人员配置无限,设置网络名称+密码!

我们打开手机或者笔记本!我们就能看到wife!这个网络就是路由器给我们实现的!

路由器既然组件的是局域网!那么路由器就只能使用如下IP了

image-20231101210623530

image-20231101210841732

==LAN口IP和WAN口IP==

image-20231101212330941

==而且从上面我们可以看出来!——私有IP是可以相同的!只要在局部上保证唯一性!全局上是可以重复的!这就决定了!只要路由器支持!我们就可以让很多重复的人!使用同一个IP来进行入网!这样就解决了IP不足的问题!==

==那么这就有一个问题了!——现在因为IP在不同的子网中可能是一样的!——我们该如何去访问?例如:我们的本地IP是196.168.1.3,目的ip可能也是196.168.1.3!==

image-20231101214438726

image-20231101215709070

==我们可以看出私网IP是不能出现在公网上的!因为私有IP在全局是会重复的!这让会路由器找不到!==

==这种在经过路由器不断的进行WAN口替换的过程的技术——就是NAT技术!==

==但是这有有一个问题!服务器是知道了应该返回到哪里了!——但是它返回的是入口路由器啊!如何找到主机呢?这里我们后面解释!至少现在我们知道了如果把数据传出去了!==

==NAT技术解决了IP地址不足的问题了!==

总结

1.一个路由器可以配置两个IP地址, 一个是WAN口IP, 一个是LAN口IP(子网IP).

2.路由器LAN口连接的主机, 都从属于当前这个路由器的子网中.

3.不同的路由器, 子网IP其实都是一样的(通常都是192.168.1.1). 子网内的主机IP地址不能重复. 但是子网之 间的IP地址就可以重复了.

4.每一个家用路由器, 其实又作为运营商路由器的子网中的一个节点. 这样的运营商路由器可能会有很多级, 最外层的运营商路由器, WAN口IP就是一个公网IP了.

5.子网内的主机需要和外网进 行通信时, 路由器将IP首部中的IP地址进行替换(替换成WAN口IP), 这样逐级 替换, 最终数据包中的IP地址成为一个公网IP. 这种技术称为NAT(Network Address Translation,网络地 址转换).

6。希望我们自己实现的服务器程序, 能够在公网上被访问到, 就需要把程序部署在一台具有外网IP的服务器上. 这样的服务器可以在阿里云/腾讯云上进行购买

==接下来我们就画一个结合私网和公网的网络拓扑结构(简单版本的)==

image-20231102110254147

假如一个漳州的用户想要,发信息给一个泉州的用户!——那么他的报文首先就会通过家庭路由器发现不是本家庭的于是交付非运营商路由器,运营商路由器一看目的IP,发现不是本地的,所以将报文转发给跨市路由器,进入公网!

然后跨市路由器检查目的IP发现是泉州的!所以就将其转发给泉州路由器,泉州路由器,然后不断的向下转发,最终找到该用户!

跨国也是同样的流程!只不过是进一步向上转发到国际路由器!

==这样子网和公网就可以结合起来了!==

现在有很多的软件,都会显示IP地址!怎么做到的!就是通过源IP来知道的!但是一般公司只能定位到省份!如果要进一步的定位市那就必须让运营商来帮助了

路由

我们今天说的路由只考虑一点!中间路由器中来了一个数据报,这个路由器该如何路由!路由器中的路由表的构成是什么样子的!

==首先我们明白一点我们在路由的时候——一定要告诉我们经过的路由器!我们去哪里!而IP协议的报头里面就有一个字段目的IP可以满足这个需求!==

==而IP == 目标网络+目标主机!所以大部分的路由我们都是在拿着目的IP先找目标主机所在的子网!——所以我们在查找的时候一定有一张对应的路由表来供我们查询!这个路由表肯定可以从我们的IP报文中提取目的网络!提取的时候肯定会配上对饮管道子网掩码!找到目标主机所在的子网后,在子网中进行内网转发,找到目的主机!——这就是一个宏观的过程!==

我们举个例子来说明一下

假设我们来到了一个新城市,想去一个地方例如清华大学,手机还恰好没电了,我们只要选择用最原始的方式来找到清华大学——问人

然后我们首先找到了一个大爷:说大爷,清华大学怎么走呀?——我们问别人的路的时候,一般会有四种结果

第一种——不知道,我也是刚来的!别问我

第二种——不太清楚,但是我知道有谁知道!你看那边的大娘!在这里十几年了!对整个城市了如指掌

第三种——认知也知道!告诉我们要怎么走!

第四种——就是找到了!大爷说:清华大学就是这这里!我是这里的保安,你要来干嘛?你说是来上学的!大爷就放你进去了

在上面的例子中,"我"就是数据包,数据包里面涵盖了一个目的地址!而大爷以及未来可能遇到的大爷,大娘!就是一个个的路由器!当我们问大爷的时候,大爷肯定也要动脑子想!大爷脑子里面全局的,或者附近局部的路径情况我们称之为==路由器内部的路由表,大爷思考的过程就是在查找路由表的过程!给我们反馈如何走就说明反馈得到了结果!==

然后我们重新看一下大爷给我们的几种反馈

第一种就是,不清楚!不知道!别问我!现实中,这样子是没有问题的!但是在路由器中这就是有问题的!路由器是不可以拒绝报文的!所以第一种情况不存在!

第二种情况,不知道!但是知道有谁知道!路由器不清楚知道报文去哪里!==但是路由器在自己不确定的情况下==,自己也必须有一个==默认路由==!——而大娘就是那个默认路由!下一条的默认网关!

第三种情况,大爷知道怎么走!==那么就是这个路由器直接给我们转发到下一跳的路由器!==

第四种情况,在上面的策略的支持下,我们成功的到达了目的地!例如:我们上面的清华大学!但是我们仅仅是为了来清华大学吗?不是我们是为了来清华大学的XX宿舍楼!所以大爷说:对你已经到了清华大学了!我们回答:那么大爷请问XX宿舍怎么走啊?大爷指了一个方向说:XX宿舍在哪里!然后我们走了一段后,终于找到了这个宿舍!——==至此我们就找到了目标网络的目标主机!这个大爷就是子网的入口路由器!==

在路上的时候我们是不会问,XX栋宿舍怎么走的!我们只会问清华大学怎么走!

==所以在路上路由的时候!我们只看目标网络!==

==只有到了目标网络我们才会去看目标主机!==

==路由的过程, 就是这样一跳一跳(Hop by Hop) "问路" 的过程.==

所谓 "一跳" 就是数据链路层中的一个区间. 具体在以太网中指从源MAC地址到目的MAC地址之间的帧传输区间

Quicker_20231102_160925_result

IP数据包的传输过程也和问路一样.

当IP数据包, 到达路由器时, 路由器会先查看目的IP;

路由器决定这个数据包是能直接发送给目标主机, 还是需要发送给下一个路由器; (每一个路由器都有自己的默认网关!如果查不到就直接发送给默认网关)

依次反复, 一直到达目标IP地址;

那么如何判定当前这个数据包该发送到哪里呢? 这个就依靠每个节点内部维护一个路由表;

Quicker_20231102_161421_result

我们可以使用如下的指令来查看路由表(linux和windows都可以!)

route

image-20231102170852829

这个是linux下的!

因为一个路由器可以有很多个的WAN口!所以自然可以连接很多个的子网!

image-20231102163031289

这个是window下的

我们需要关注的字段有:Destination,Getway,Genmask,iface,flag

==我们可以举几个转发的例子!==

假设某主机上的网络接口配置和路由表如下:

Quicker_20231102_163408_result

这台主机有两个网络接口,一个网络接口连到192.168.10.0/24网络,另一个网络接口连到 192.168.56.0/24网络;

路由表的Destination是目的网络地址

Genmask是子网掩码

Gateway是下一跳地址

Iface是发送接 口,Flags中的U标志表示此条目有效(可以禁用某些 条目),G标志表示此条目的下一跳地址是某个路由器的地址,没有G标志的条目表示目的网络地址是与本机接口直接相连的网络,不必经路由器转发

转发过程例1: 如果要发送的数据包的目的地址是192.168.56.3

==跟第一行的子网掩码做与运算得 到192.168.56.0(按位与的本质是确认报文要去的目标网络)==,与第一行的目的网络地址不符

再==跟第二行的子网掩码做与运算得 到192.168.56.0==正是第二行的目的网络地址,因此从eth1接口发送出 去;

由于192.168.56.0/24正 是与eth1 接口直接相连的网络(没有G标志)因此可以直接发到目的主机,不需要经路由器转发;

image-20231102164543316

==其实查找的过程很简单!1.遍历路由表!2.目的IP & 路由表中的子网掩码!确认目标网络!3.对比结果!4.通过某个接口将报文发出去!==

转发过程例2: 如果要发送的数据包的目的地址是202.10.1.2

和路由表前几项进行对比, 发现都不匹配;

按缺省路由条目, 从eth0接口发出去, 发往192.168.10.1路由器;

192.168.10.1路由器根据它的路由表决定下一跳地址

image-20231102165128070

那么当我们进行数据报转发的时候——我们的==目标网络号==会不会发送变化呢?==肯定会!我们要明白——最终的目标网络不等于目标网络号!==

我们每次要去的下一跳,目标网络号都是在改变的!也就是每个路由表的destination这个是不同的!但是我们报文里面的目标IP是一直不变的!

路由表生成算法

路由表可以由网络管理员手动维护(静态路由), 也可以通过一些算法自动生成(动态路由).读者有兴趣可以自己调研一些相关的生成算法, 例如距离向量算法, LS算法, Dijkstra算法

16位标识符,3位标识与13位片漂移

我们上面解释IP协议的时候故意忽略了中间的那一层字段没有讲!这是因为这和我们后面要讲的数据链路层有关的MAC帧协议有关!

真正的在路由器路由器传递的确实是IP报文!但是真正的网线上跑的是MAC帧!

当IP报文向下交付给数据链路层后!就会被加上报头,变成MAC帧报文!——而MAC帧报文有一个规定!自己的==有效载荷不能超过1500字节==!(MTU最大传送单元——但是这是可以修改的,只不过一般是1500字节)==这个1500是IP报头+IP报文的有效载荷==

==但是IP协议能决定单个报文的大小呢?——不能!因为我们上面说过IP层本身也只是办事的!==

image-20231102173916221

TCP可以控制什么是时候发送!发送的大小是多少!IP本身只是提供路由功能!

==但是假如传输非要让IP报文的大小一次性塞了3000字节呢?==

就像是我们现实中,大领导发了一个不可能完成的任务,你是一个小组长,而你的手下说这个根本完不成,左右为难,两边受气!只能自己想办法

因为IP报文过大这样子数据链路层就无法发送了!所以为了解决这个问题于是有了==分片与组织!==

==我们要首先明确一点——IP的分片与组装不是主流情况!==

那么分片应该由谁来分片?组装应该由谁来组装?——分片的信息在谁的报头里面就属于谁的工作!那么谁就要来进行分片和组装!==所以分片和组装是属于IP层的工作!==

就好比,我们今天去楼下一个的快递点去快递一个台式机,快递台式机的时候,快递点的员工说,单个物件的重量不能超过2公斤!因为快递公司不愿意担责,所以要求我们自己将台式机拆开!**所以将台式机拆成好五个包裹!**快递公司不关心自己运的是什么!直接将5个包裹发出去了!当你朋友收到包裹后!会不会觉得快递公司怎么搞的!怎么会吧一个电脑变成五个包裹呢?——不会因为朋友也知道快递公司有规定,如果整机发过来就超重了!

你朋友说:快递小哥能不能帮我,组一下整机呢?快递小哥肯定要是拒绝的!因为快递公司只负责传输!所以只能由你朋友自己来拼

==所以有发送方的IP层负责分片!对端的IP层负责组装!==

站在MAC帧这一层,MAC帧是不关心IP到底分片了没有!只关心报文到底有没有超过规定大小!

那么发送方TCP关不关心IP报文的分片和组织呢?——肯定不关心!如果TCP层真的关心就不应该发那么大的报文给IP层!

接收方的TCP也不关心!对方TCP发送3000字节!那么接收方也只要关心接收3000字节!

==所以分片和组织是纯纯的IP层自己的行为!——所以在逻辑上就要和TCP与MAC进行解耦!==

==那么如何进行分片和组装呢?==

image-20231103113528697

==基于上面的五个问题我们首先来认识一下这个三个字段的功能==

==16位标识(id): 唯一的标识主机发送的报文. 如果IP报文在因为数据链路层规定而导致在IP层被分片了, 那么每一个片里面的这个 id都是相同的.==

==3位标志字段: 第一位保留(保留的意思是现在不用, 但是还没想好说不定以后要用到). 第二位置为1表示禁止分片, 这时候如果报文长度超过MTU, IP模块就会丢弃报文. 第三位表示"更多分片", 如果分片了的话, 最后一个分片置为0, 其他是1. 类似于一个结束标记==

第二位为1这个选项一般在路由器中被配置!用于过滤掉一些大报文,但是绝大部分的情况(99%)都是为0的

比如说一个报文被分片为3个,第一个,第二个都是被置为1的!最后的第三个会被置为0

如果没有分片,那么就会是0,这个第三位表示的是我的后面还有没有报文!如果为1就还有,如果为0就没有更多分片!也解决了问题0

==IP报文进行分片的时候不是简单的一刀切的分割!而是每一个被分片的部分都要重新封装上IP报头!合并的时候将多余的报头去掉即可!==

==13位分片偏移(framegament offset): 是分片相对于原始IP报文开始处的偏移. 其实就是在表示当前分片 在原报文中处在哪个位置. 实际偏移的字节数是这个值 * 8 得到的. 因此, 除了最后一个报文之外, 其他报文的长度必须是8的整数倍(否则报文就不连续了)==

image-20231104155343963

==那么我们可以扩展一些问题==

1.分片好吗?——不好!

2.对TCP和udp包括IP本身有什么影响吗?

分片问题对于TCP和MAC帧它都不关心!也就是TCP的角度,它只是发了一个最终也收了一个!可是实际底层它可能发了2.3个甚至更多个

其中任意一个报文丢失就会导致拼接组装失败!从而要求发送方重新发送!==而重新发送肯定是要整个报文一起重新发送的!因为TCP不关心,也不知道分片!在TCP看来就是只发了一个报文!也不知道分了几个片,这都是IP自己的行为!==

==所以当一个报文被拆成了多分,任意一个报文分片的丢失就会导致拼接组装失败!进而导致对端对整个报文进行重传!==

那么这又有什么问题呢?——报文丢失不是很常见吗?如果一个报文不丢包的概率是99%,如果我们把一个报文拆分成3片,每一片丢失的概率也是99%,那么如果要让这个报文不丢包,那么概率就是约是97%==所以我们可以得出一个结论!分片会增加丢包的概率!==

所以我们一般都不建议进行分片!——或者说如何减少分片!

==为了更好的理解我们可以自己试着分一下片==

image-20231104164530351