目录
网络层交给数据链路层的数据大小是有约束的。换言之如果IP报文太大,该如何处理呢?
请问这个分片的过程传输层知道吗?怎们在技术层面保证传输层不知道呢?
我可以上网的时候,不给运营商交钱,就想直接访问别人的服务器,可能吗?
为什你欠了话费不能给其他人打通电话,但是你确能给运营商打通电话?
实际生活中,我们发现只要欠费了,你自己是交不了的,你必须得让你朋友交或者连上WiFi缴费,为什么移动不把这个缴费的接口放开呢?
我想把我的数据直接通过运营商路由器去转发,而不经过公网,这能做到吗?
为什么我经过不断的去查找路由表,直接就可以不断的去跳转到下一跳,然后找到目标网络呢?
在局域网中做数据转发的时候是基于碰撞检查,碰撞域这样的策略去做的,所以为什么数据帧的物理层为什么要规定1500字节?(虽然这个值可以改大也可以改小,但是基本上都是1500)
主机A收到来自主机B的数据帧,为什么不直接从以太网首部这里提取主机B的mac地址呢?
主机A经过路径选择到达了入口路由器然后到达主机B,难道每一次向主机B发消息都要进行ARP请求吗?
如果我今天想知道和我处于同一个局域网内所有主机的mac地址,怎么办呢?
有些面试官可能会问: telnet是23端口, ssh是22端口, 那么ping是什么端口?
如果客户端A从来没有访问过服务器,服务器能否访问客户端A吗?
我们一般在云服务器上是没有办法绑定自己的公网ip的,为什么呢?
为什么socket通信时服务端不能绑定云服务器的公网ip及为什么要绑定INADDR_ANY?
网络层与数据链路层
我们学TCP的时候,TCP说是把报文从我的服务端发送到了对端,这真的是把TCP报文发送过去了吗?
答案当然不是,真实的网络通信时贯穿协议栈的,是自顶向下的。就好比人不能直接从3楼直接凭空飞到对面的3楼,而是必须得下楼,再上楼,才能过去。换言之,TCP封装好的报文不是直接发出去的,而是要将TCP的报文再次向下交付,通过IP协议进行路由转发,转发到目标主机。
当然难道是IP报文直接发出去的吗?
答案也不是,实际上底层的数据链路层到物理层,真正的数据是在链路上跑,经过各种硬件设备转发到了目标主机,再进行自底向上交付到了你的网络或者传输层才能被对方收到。我们之前说的都是忽略了TCP下层的通信细节。所以当你学习当前层的时候,要弱化下一层协议的猜测,只是站在功能角度认为下层给我提供这样的功能了。
以主机B和主机C为例,之前我们学习的:只考虑主机B和主机C,HTTP只考虑应用层,传输层只考虑了主机B和主机C两端的问题,路上的问题我们并没有考虑。如果你的报文要到主机C,前提条件必须经过这么多路由器才能到达对端。
网络层
IP协议
IP的构成
IP=网络号+主机号。
从生活当中的例子引出:
人分布在不同地区的,比如你想去天安门广场,是不是你就乘坐交通工具一次到位,直接就到天安门广场门口,实际并不是。比如,你要去天安门,别人问你去哪,你首先说的是我要去北京。所以当你到达了北京,你在乘坐北京内部的交通工具:地铁,公交...然后在到达对应的景点。
再好比,唐朝取经,他永远说的是平僧自东土大唐而来,要到西天拜佛求经。实际上去西天不是他的目的,他正在要去的是到了西天以后,在去大雷音寺,然后在面见佛祖。
我们到北京,到西天叫做先找到去的地点所在的网络号,到了目标子网之后,我们再在子网中找对应的主机号,就好比到了天安门,大雷音寺。剩下的工作就是封包,解包,就好比到了天安门广场的找到了某个导游,到了大雷音寺找到了如来佛祖。这个就是应用层特定的一个人提供服务。
我们实际上路由查找的时候不是完全按照目标主机去找的,而是先找网络号,再找主机号。
TCP和IP各自解决什么问题?
在自然世界中,人类解决问题,无非就是就解决两个问题,决策问题和执行问题。
eg:你和你的朋友要吃饭,就先决策中午吃啥,决策好吃饺子,让后去食堂吃饺子这就是执行。我们这个世界上永远是有人在做决策,有人在做执行。当然对于人很多时候都是既做决策又做执行。
对于计算机,决策和执行则是分开的。如果混在一起则导致业务逻辑非常的不好写,非常混乱,所以把他们分层之后,进行所谓的逻辑层面的解耦能让我们的维护成本降低。
TCP层一定是将自己的报文交付给下层,让IP进行路由转发的,TCP是保证可靠性的,IP是不保证可靠性的,如果TCP是给我们提供一整套的保证可靠性和提高效率的策略的话,IP则提供了一种能力,将数据从A主机跨网络传送给主机B的能力。只有IP具备了这个能力,TCP才能把报文交给IP,然后封装上IP的报头,进而把IP数据包从主机跨网络传送到主机B,这个时候才有意义,到达主机B之后,在进行向上交付分用,将对应的ip报头去掉,再交付给TCP,此时这个TCP才被主机B在传输层收到对应的数据。
比如你是学校的学生,你的成绩非常好,你考试的时候较大概率能考到满分,你去考试的过程就是你去做执行的过程,因为你要执行一次考试,那么如何保证100%拿到满分呢?
很显然单靠你自己是不行的,而你有一个非常牛的爹,你爹是学校的教务主管,他能组织学校考试的时间,地点,甚至是重考。那么你就去考试,如果你这次没考到满分,你爹就给你单独组织一次重考,如果还没满分,就继续重考,因为你有较大的概率能考到满分,所以经过不断重复,就可以让你100%考到满分。
其中,你做的工作就是执行,你爹做的工作就是做决策,你爹给你的决策就是如果你没考到满分,就让你再考一次,上次没考满分的原因是因为你太着急了,你爹就告诉你,下次考试我给你延长时间;上次考试是因为环境太吵,影响到你了,你爹就把场清了,让你一个人考试。其中你爹给你提供一种不断让你试错的决策能力,这个就相当于是TCP解决的。而你提供了一种能力,不断进行考试有较大概率拿到满分,这就叫做IP层解决的问题。
你告诉你爹没考满分是因为时间不够了,你爹就把时间给你延长了,这就叫做流量控制;你上次考试是因为环境太吵了,你爹就把场给你清了,这就叫做拥塞控制。
换言之TCP和IP相比,TCP更强调的是TCP给我们提供的一个一个的策略机制,IP更强调的是将数据以较大概率从主机A送到主机B。IP重要的是执行能力,它能帮你把数据从主机A送到主机B。较大概率意味着大部分情况下不会出错,也就意味着IP层不提供可靠性机制,你只需要把你的能力用好就行了。因为IP的脑袋上还有TCP,TCP的超时重传就是IP没把数据传过去,TCP就让IP在来一次,超时重传,快重传,拥塞控制...所有的机制都是为了把数据包发到网络里,出问题了,底层交付给TCP层,然后TCP层就让他们再来一次,所以TCP给了IP压力,让IP不断进行各种基于TCP策略之下的各种执行动作。
基本概念
- 主机: 配有IP地址, 也是会进行路由控制的设备;
- 路由器: 即配有IP地址, 又能进行路由控制;
- 节点: 主机和路由器的统称;
后序文章中,像用户具体使用的设备,端到端的,我们叫主机;路上的这些点到点的路由器设备,我们就叫节点。
协议头格式
- 4位版本号(version): 指定IP协议的版本, 对于IPv4来说, 就是4.
- 4位头部长度(header length): IP头部的长度是多少个32bit, 也就是 length * 4 的字节数. 4bit表示最大的数字是15, 因此IP头部最大长度是60字节.
- 8位服务类型(Type Of Service): 3位优先权字段(已经弃用), 4位TOS字段, 和1位保留字段(必须置为0). 4位TOS分别表示: 最小延时, 最大吞吐量, 最高可靠性, 最小成本. 这四者相互冲突, 只能选择一个. 对于ssh/telnet这样的应用程序, 最小延时比较重要; 对于ftp这样的程序, 最大吞吐量比较重要.
- 16位总长度(total length): IP数据报整体占多少个字节.
- 16位标识(id): 唯一的标识主机发送的报文. 如果IP报文在数据链路层被分片了, 那么每一个片里面的这个id都是相同的.
- 3位标志字段: 第一位保留(保留的意思是现在不用, 但是还没想好说不定以后要用到). 第二位置为1表示禁止分片, 这时候如果报文长度超过MTU, IP模块就会丢弃报文. 第三位表示"更多分片", 如果分片了的话, 最后一个分片置为1, 其他是0. 类似于一个结束标记.
- 13位分片偏移(framegament offffset): 是分片相对于原始IP报文开始处的偏移. 其实就是在表示当前分片在原报文中处在哪个位置. 实际偏移的字节数是这个值 * 8 得到的. 因此, 除了最后一个报文之外, 其他报文的长度必须是8的整数倍(否则报文就不连续了).
- 8位生存时间(Time To Live, TTL): 数据报到达目的地的最大报文跳数. 一般是64. 每次经过一个路由, TTL -= 1, 一直减到0还没到达, 那么就丢弃了. 这个字段主要是用来防止出现路由循环
- 8位协议: 表示上层协议的类型
- 16位头部校验和: 使用CRC进行校验, 来鉴别头部是否损坏.
- 32位源地址和32位目标地址: 表示发送端和接收端.
- 选项字段(不定长, 最多40字节): 略
协议头分析
ip的标准报头长度20字节,宽度32个比特位。也可以携带选项,也有4位首部长度(单位也是4字节),所以我们立马想到TCP的报头。IP的报头风格和TCP一毛一样。所以我们学习的网络协议栈是用TCP/IP命名的,因为从协议当中就能看出来,TCP和IP的报头长度是一模一样的。当然细节肯定不一样。
如何分离与封装?
因为有4位首部长度,我们收到一个完整的IP数据包,就可以无脑读取前20个字节,然后提取4位首部长度,确定它有没有选项,没有选项剩下的就是有效载荷。这就做到了分离。
另外它还有16位的总长度。IP不是字节流的,TCP是字节流的,这个字节流是站在应用层HTTP的角度,我们曾经写的套接字角度看待TCP,它是字节流的。可是我们发现TCP底层用的IP,它的报文也必须一个报文一个报文发出去,只不过发出去之后,在TCP那里组合起来交给TCP,写到TCP的缓冲区里,TCP是以流式的方式呈现给应用层的,而底层还得是一个个报文。所以它有16位总长度。所以IP报文要交付给上层的UDP和TCP,就也需要解决它自己的粘包问题,所以它也需要把报文和报文之间的边界区分开。所以4位首部长度和16位总长度就能够区分自身报文的报头和有效载荷。
封装报头的时候有选项直接加选项,报头多长就填4位首部长度,有效载荷多长就填16位首部长度。
如何分用(向上交付)?
IP解完包后,如何将自己的有效载荷交给上层协议,IP脑袋上是传输层,是UDP或者TCP。ps:如果是原始套接字,IP脑袋上可能就是应用层。
IP就可以通过8位协议做到将自己的有效载荷交付给上一层的哪个协议,8位协议里面填充的就是上层的协议是谁。但是一个IP报文并没有能力知道自己要把数据交给谁。
8位协议字段站在一个收到报文的角度,它可以根据8位协议字段决定这个数据应该交付给上层的谁。可是这个8位协议是谁填充的呢?
是IP吗,IP没和这个能力,因为IP无法决定自己的有效载荷交付给谁。这个8位协议是上层填的,如果是UDP填的,8位协议写的就是UDP,如果是TCP填的,8位协议就填的是TCP。所以一个UDP的客户端是不能和TCP的服务端通信的,因为所有的报文都是由上一层的TCP或者UDP交付给下一层IP的,所以上层再交付的时候,它要参与IP报头字段的填充,上层TCP在填写8位协议时,这个报文数据也一定是传给对方的TCP。换言之,就是上层给他填写的这个8位协议,所以到了对端,对端就可以交付给对等的上层协议,所以这里就不会出错了。所以8位协议用来解决分用问题。所以这也就是为什么UDP只能和UDP通信,TCP只能和TCP通信,因为上层交付给下层的协议报文8位协议填写的就是TCP或者UDP自己。
16位首部校验和
- 报文说白了就是光电信号在硬件上,如果因为硬件故障导致报文出现了细微的比特位翻转,把某些比特位由0置1,由1置0,这个报文就出问题了,所以不光要保证字段要正确,数据也要正确。你要保证正确就进行校验。
- 通过校验和确认IP的组装情况。
32位源IP和目的IP
一个报文就得告诉我你从哪来要到哪去。 唐朝取经,他永远说的是平僧自东土大唐而来,要到西天拜佛求经。 源IP和目的IP就是东土大唐和西天。
IP解决的就是把数据从一个主机到另外一个主机。解决的就是机器到机器的问题。TCP和UDP里携带的是端口号,它要解决的就是从主机上把数据交付给应用的问题。
4位版本
基本上没意义,一般是IPV4。
注意:这个4位版本不能填写IPV6,IPV4表示的ip地址是32个比特位。IPV6表示的ip地址是128个比特位。IPV4和IPV6是不兼容的。网络世界已经通过IPV4构建起来了,IPV6又没有构建起来,又和老的IPV4不兼容,此时就很糟糕,没有办法统一在全网中切换到IPV6,只能慢慢迁移。现在引入IPV6只能是推到重来,有些公司组建机房天然就用IPV6,相当于内网是IPV6,通信外网是IPV4。实际上,双方ip地址解耦是通过数据解耦的,相当于我给你发数据,你在内部处理你的,我路由我的,互不干扰。所以这里的4位版本没有意义,就是IPV4,IPV6就是另外一套协议了。未来是有可能都是IPV6的,但是还早,不兼容导致迁移的成本非常高,所以只能是在有新的网络设施架设起来的时候采用IPV6,当网络世界的基础设施使用IPV6的设施变的非常多的时候,IPV4使用比重降的比较低的程度下,这个时候才可能用规模效应挤压IPV4的市场,让IPV4退出历史舞台,现在还早,预计未来几十年IPV4和IPV6都是共存的状态。
8位服务类型(Type Of Service)
8位生存时间
在IP报文里面,源IP和目的IP是最重要的,因为报文在路上转发的时候,大部分我们所考虑使用的字段就是这个两个源IP和目的IP,如果再要挑一个重点字段,一个报文在转发的时候最重要的就是目的IP这个字段,对比其他字段,就相当于一个王者带一堆青铜。
分片问题
为什么会分片?
正常情况下,应用层传下来的一个数据就可以交付给传输层,传输层添加上自己的报头然后交付给网络层,网络层添加上自己的报头然后交付给数据链路层。报文不断向下交付过程,我们称之为封装的过程,我们既然称其为封装的过程,我们的网络层将来把他的报头在内也是需要向下交付封装的。但是数据链路层有一个规定:数据链路层一次可以往网络里发送的数据大小是有限制的,我们称之为MTU。MTU在绝大多数主机当中都设置为1500字节。![]()
mtu表示最大传输单元,就是1500。
网络层交给数据链路层的数据大小是有约束的。换言之如果IP报文太大,该如何处理呢?
你现在MTU底层的协议告诉我,我们的数据链路层最多能接收1500字节,可是网络层交给你2000字节,那么此时数据链路层该怎么处理呢?或者网络层,IP协议该如何处理呢?
比如说,你今天给你朋友邮寄了一台台式机,里面有主机,显示屏,键盘,鼠标,你去把你的这一批设备拿到快递公司,你给快递公司说能不能把我这一批东西邮寄到北京。快递公司告诉你,对不起,我们每次单个快递包只能是5千克,你这个电脑是15千克,得分3个包裹。因为快递公司单个包裹的重量限定,此时就需要你把你要发送的资源进行分包,请问这个分包工作由谁来做比较好呢?
为什么要在网络层进行分片?
正常情况下,肯定就是直接让快递公司进行分了,但是在计算机里面,我们要把它解耦解的非常好的话,我们就应该想清楚到底由谁来做。就单单拆电脑的情况快递公司是不会做的,万一拆了以后到对端组装不起来就是快递公司的问题。所以快递公司不帮你拆这个东西,你自己拆,我的要求就是每个包裹5公斤,拆完以后你给我就可以了,你给我啥我发啥,最后对方收到了能不能组装起来快递公司不关心,也不负责。
同样的,在网络报文里,实际上分片或者把报文拆成多个的工作实际上就应该是网络层需要做的,因为你把报文由一个变三个,也要保证你拆出来的报文不是只有数据,它也要在网络里传送的,它也需要IP地址,所以你在拆报文最后也是要给拆出来的报文在添加报头的(IP的报头),要不然我们的数据包也就没办法在网络里经过路由转发了,所以必须得在网络层里对它拆,必须得报文重新添加IP报头。当然如果你的报文是头部的本来就有报头,其实就不用添加了,但是多出来的报文必须添加报头。
这不能在链路层做就是因为链路层无法得知,也不需要知道网络层的任何细节,如果要在链路层分片的话,就一定要保证链路层知道网络层的IP地址,端口号,然后给新分的报文添加IP报头,这就不是链路层该做的,所以分片工作必须得在网络层做。PS:链路层也不是不能做,但是一做,耦合度就提升上来了,就非常的不好。
谁来进行分片组装呢?
所以我们在分片的时候必须得包含所有的分片细节,如果你只负责分片,一刀切,分完之后直接添加报头,什么信息都不做调整或者添加,那么最终我们的整个报文也就没有任何的组装细节。没有任何组装细节的话,对我们也就毫无意义。谁分片,谁组装,因为分片是在网络层里做的,所以组装一定是对端的网络层IP协议进行组装。理由如下:
- 分片之后所有报头信息的识别只有对端网络层需要,有义务进行识别,而且只有他能进行是识别。
- 我们添加的这些分片的网络细节,也只有网络层清楚。
什么是分片?
其实就是把报文切成了多片。
如何进行分片?
比如说,网络层收到了一个报文,它的大小就是1500字节,现在要把这个1500字节交给链路层,按照逻辑来讲是可以直接交付的,但是不要忘了网络层还有20字节的报头,所以网络层从传输层这里拿下来1500分数据,要添加报头就需要有1520个字节交给链路层,可是链路层只能传1500字节,此时网络层它要向下交付就必须对1520这个报文进行分包,1520包括了1500的有效载荷+20字节的报头长度。现在要分包的话就必须把1520分成2个包。关键是分的两个包的大小是多少呢?而且分的这两个包必须都得添加报头。
数据链路层最多就是1500,而且这个1500是包含网络层的报头的,意味着链路层传送的有效载荷最多是1480个字节。
所以我们将这1500字节至少拆成:1480+20;
- 将1480添加20字节的报头,形成第一个1500的报文,此时就可以直接通过链路层发送;
- 另外20字节,也要添加20字节的报头,形成40字节的报文,然后交给链路层发;
所以这个时候才能进行向下进行数据转发。
实际上网络层在进行分片的时候,它收到了传输层的数据,假设收到的传输层的数据报文是X,那么网络层就进行以下算法分片:
最终我们的结论就是:分片其实很简单,如果网络层的数据太大,那么我们在分片的时候只需要考虑将我们的数据分成多片,但是一定要考虑每一片都要有报头,如果今天网络层告诉你我要传送的数据字节数是1520,是包含了所谓的报头的;那么你一定要考虑,它本身如果有网络层的报头的话,你要把这个20作为第一个报文,剩下的1500,带入到上面的算法中进行分片,然后在和原生的这个20报头一加,然后交付给数据链路层就可以了。
eg: 分片
1.0 假设网络层里有个3420字节的报文且这个3420是包括网络层的报头的
2.0 假设网络层里有个3420字节的报文但是这个3420是不包括网络层的报头的
![]()
ps:进行分片的时候,一定要知道交给链路层的报文有没有携带网络层的报头,如果没有携带就直接按照链路层MTU的要求,直接把报文拆成若干个,然后再把每一个添加报头;如果你本身就添加了报头,我就需要把原生的这个报头作为待会拆分下的新报文需要添加的报头。
最终结论:每个分出来的报文,都必须要有报头。
组合问题
除此之外,我们还要考虑组合的问题!!!
比如:传输层告诉网络层传3400个字节,网络层收到的就是3400字节+20字节(自己的报头)=3420个字节,3420要发送给链路层,但是不符合规定,就只能进行分片,然后就变成了3个报文:1480+20字节,1480+20字节,440+20字节;
此时到对端的链路层就直接发了3个报文,对端的链路层交给网络层肯定也是3个报文。
请问这个分片的过程传输层知道吗?怎们在技术层面保证传输层不知道呢?
网络协议栈是解耦的,当前层根本就不关心下面所有层的通信细节。所以传输层不知道。
所以底层一旦分片,经过网络也分片传送,到了对端链路层向上交付,如果网络层不做任何处理,网络层向上交付的也是3个报文,那么传输层就知道了。所以当网络层收到这3个报文时需要进行组装,组转好向对应的传输层交付,也就是说,只要我能组装好,你曾经在对端传输层你给我网络层的是什么样子,我在对端的网络层交给你传输层的也就是什么样子,这样的话,我在网络层的分片,在网络层的组装你的传输层也就不需要知道了,我也就相当于对传输层做了相关的隐藏。所以只要在网络层可以做好分片,组装工作就能保证传输层是0感知的。
比如:旧社会,皇帝和财政大臣说要100万两白银,财政大臣总不能和皇帝说有难处啥的,所以只能答应,过了一个月,财政大臣就把100万两白银交给皇帝就可以了,至于财政大臣在底下是各种搜刮民脂民膏就是他的事情了。
对我们来讲,网络层到链路层以及网络层把数据报文交给传输层,只要你把分片组装工作做好,那么对于传输层就是透明的
这个分片的过程传输层需要知道吗?
不需要知道
分片真的好吗?
一旦分片之后,万一有一个报文丢失了该怎么办呢?
就比如上面的例子,分片后变为3个报文,而我就丢一个报文,丢失一个报文的时候,网络层就无法组装了,此时的报文就变的残缺,传输层给了网络层3400,网络层也必须得给传输层3400,所以万一有一个报文丢了就是组装失败,组装失败以后整个报文全部丢弃,也就意味着传输层交给网络层的3400个字节,在对端传输层一个字节也收不到,所以对应的就是传输层认为数据包丢包了,丢包了以后就进行重传,重传传输层在传入3400,然后在重复刚才的过程,如果还是在丢失的话,就继续进行重传,所以分片的缺点就是可能提高丢包的风险。
比如:快递公司丢一个快递的概率是1%,如果你把一台电脑由一个包裹分成3个包裹,只要任何一个包裹丢了,那么这台电脑你就用不了了,所以你丢包的概率就几乎提升了3倍。相当于我们如果造成过多分片的话是会导致我们有丢包风险的。
可是你别忘了,如果传输层是TCP还好,它能进行重传,可是如果是UDP(TCP/UDP底层都用的是IP)本来它就不保证可靠性,你还在底层进行分片,这个时候如果丢包了,就只能组装失败,然后这个报文就跟着丢了。
所以分片是可能提高我们丢包的风险的,所以我们一般不建议分片,所以IP分片不是大部分情况,我们只有特殊情况才会分片。
如果我压根就不想分片了,谁说了算?
协议无非就是应用层,传输层,网络层和链路层,如果今天压根就不想分片。链路层受硬件的约束,这个MTU只能是1500,链路层只是定制一个标准,分不分片链路层说了不算;网络层就是做执行的,传输层发数据过来,网络层添加上自己的报头然后交付给链路层,网络层也没有办法,所以网络层说了也不算,再者,如果网络层如果说了算,还需要给自己的报文里添加分片和组装的字段吗,它直接把报文控制的不要超过1500就行了;所以只能是传输层说了算,因为是传输层决定是什么时候发?发多少?出错了怎么办?如何发的问题。所以之前我们讲TCP协议,在进行网络传送的时候,每一个报文,我们都没有规定它的大小,但实际上,我们在网路协议设置的时候,传输层在和对端通信的时候,会和对面的传输层协商每次传输的单个报文的大小 ,所以传输层只要保证自己交给我们网络层的大小是1480个,那么向下再走的时候,就不会进行分片了。所以,我们要让报文不分片是传输层说了算,传输层确实不知道你分片了,但是传输层可以帮助你还是不要让你在底层出现太多的分片。我们重点说的是TCP。
一般而言,我们为了减少分片,一般是要TCP控制自己的单个报文的大小的。
16位标识
IP报头里包含了3个重要的字段:16位标识
16位标识:我们收到了大量的IP报文,如果大家没有任何分片,那么每个报文的16位标识全部都是不一样的,也就是每个IP报文都有自己的标识。如果没有分片,不同报文,标识符是不一样的;如果分片,标识符是一样的!
比如:我是一个接收方,我将来可能会收到大量的IP报文,如果这些报文中的标识符都不一样,那么每一个报文都是一个个独立的报文。如果你将来分片,分片后的报文每一片都要有报头,就意味着每一片的标识符是一样的,只有标识符是一样的,我们才能把他们拿在一起。
13位片偏移
片偏移对应第一个报文就是0;第二个报文就是1480,意思就是说我这个分完的片,偏移量在原始报文偏移量位1480的部分。第一个报文的偏移量+第一个分片后的长度就是第二个报文的偏移量。
所以我们就可以把标识符相同的报文按照片偏移组合起来。
13位片偏移:我的报文的有效载荷,在原始报文的有效载荷中的偏移量。
16位标识位是把大家聚在一起,13位片偏移就是把大家组合在一起。
分片后如何组装呢?
只要根据偏移量升序排序就可以了。
我怎么知道,有没有报文丢失了呢?
丢包一共3种情况:
- 整个报文的最开始丢了;
- 中间的部分丢了;
- 最后的部分丢了;
开始丢了:我排序之后,只要发现片偏移为0的报文没有就说明是头丢了;
中间丢了:一定是收到了头,收到了尾,排序之后,我可以做一次检测,从第一个报文的偏移量+它自己分片的长度就应该是下一个报文的起始偏移量...经过这样的方式,我们就可以有效甄别出中间有报文丢失的情况,也就是说如果整个计算不连续了,肯定是这个报文丢了。
所以前面丢了和中间丢了,我们一点也不害怕,我们完全可以通过片偏移确定出来。
尾部丢了:我们最担心尾部丢了,你怎么知道尾部的丢了呢?
3位标志
我们不用担心,我们有3位标志
3位标志:1位保留,1位禁止分片(我很强硬,我给链路层1800个字节,可链路层只能传1500,如果我设置了这个标志位,那么我就不能分片,我把这个1800字节的报文丢了,都不能分片),1位标识更多报文或者更多分片(这个标识位如果为1,标识后面还有更多的分片,如果为0标识后面没有分片了)。区分最后一个报文,以及确认是否收全了所有的报文。只要把头和尾找到了,中间有没有收全我们就可以通过片偏移判断了。
换言之,我们收到的报文如果是第一个报文或者是中间报文,它的更多分片位都是被置1的;如果收到的是最后一个报文,它的更多分片位就是被置0的。
接收端如何得知报文是独立的还是一个分片的?
上面我们是已经假设是分片的,所以我们可以知道如何填16位标识,3位片偏移,3位标志。可是对端主机收到的IP报文一定是混搭的,既有分片报文,又有正常报文,所以我们要能够执行各种组合操作,前提条件是接收方能判断对应的报文是有分片的或者是正常报文,对于正常报文就直接向上交付了,对于分片报文就进行组合,排序。
我们通过13位片偏移和3位标志就可以确定报文是独立还是分片的:
首先通过16位标识是完全分不出来的,我们必须具体的判断出某一个报文是不是分片的。所以我们可以通过片偏移量,如果你是独立报文,你的片偏移量一定是0;对于分片的第一个报文(片偏移量也是0),对于它我们就可以通过3位标志的更多分片标志位判断(一定是1)。
所以接收数据的一方:检测3位标志的更多分片标志位是否为1以及检测13位片偏移是否不为0,只要你的3位标志的更多分片标志位是1或者13位片偏移不为0那么你就是一个分片报文。然后在根据16位标识把他们放在一起,然后组合排序就可以了。
- 第一个分片报文:更多分片标志位是1,13位片偏移是0
- 中间分片报文:更多分片标志位是1,13位片偏移非0
- 最后一个分片报文:更多分片标志位是0,13位片偏移非0
对于正常报文:
- 更多分片标志位是0,13位片偏移是0。
ip分片丢包了如何重传呢?
只要在组装的时候识别到上面所说的任意一种情况,ip就不将数据向上交付,随着而来的就是TCP的重传。
因为 IP 层本身没有超时重传的机制——由更高层来负责超时和重传( TCP 有超时和重传机制,但 UDP 没有。一些 UDP 应用程序本身也执行超时和重传)。当来自 TCP 报文段的某一片丢失后,TCP 在超时后重发整个 TCP 报文段,该报文段对应于一份 IP 数据报。没有办法只重传数据报中的一个数据片。事实上,如果对数据分片的是中间路由器,而不是起始端系统,那么起始端系统就不无知道数据报是如何被分片的,因为这个原因,经常要避免分片。
网段划分
- 网络号: 保证相互连接的两个网段具有不同的标识;
- 主机号: 同一网段内, 主机之间具有相同的网络号, 但是必须有不同的主机号;
eg:下图这两个大方框对应的就是两个网段,如果你不理解网段,你就可以把理解成这是两个不同的局域网,这两个局域网之间用路由器连接起来,其中这两个个局域网所对应的网络标识在同一个网段内,所有主机的网络标识都是一样的,第一个网段内就叫192.168.128;另一个网段的网络标识是192.168.144。大家在不同网段中,网络号是完全不一样的,在同一个网段内,网络号是一样的,这就是网络号的概念。在同一个局域网内,大家的主机号是不一样的,如图都是10和11号。
局域网双方是通过路由器连接起来的,路由器会记住192.168.128,192.168.144这样的网络标识,因为路由器本身是横跨至少两个子网或者网络的,所以路由器在上面的这个子网看来,也必须配有IP地址。一般而言,你的网段内的第一号主机通常是给路由器的,在第一个网络里的标识是182.168.128.1,在第二个网络里的标识是192.168.144.1。路由器是负责跨网络传送的,所以路由器必须至少有两套网络接口(说人话就是必须得配两张网卡,每张网卡里各种配一个ip) ,路由器必须横跨至少两个网络,要不然它就没办法进行网络转发。所以有路由器的存在我们就可以将数据从一台主机转发至另外一台主机。
比如:第二个网段内的主机发出一条数据,目的IP写上192.168.128,当它把数据发出去的时候,它立马就可以判定这个数据不是给我当前局域网内的主机发送的,所以我就把他扔给了路由器,路由器因为横跨了两个网络,所以它对两个网络都认识,它内部查路由表发现你要去的目标网络就是192.168.128,主机号比如说是10号,所以路由器就可以把报文转发给10号了。
换言之,我们可以通过路由器桥接两个不同的网络,路由器在每一个网络内部都必须认为,它也是这个网段内的一个主机。
IP地址是32位的,所谓的网络号或者主机号说白了就是把我们对应的32个比特位进行比特位的划分,前面的若干比特位标识网络号,后面的标识主机号。不同的子网就是把网络号相同的主机放在一起,如果你在子网当中新增一台主机,那么这台主机的网络号和这个子网的网络号是一样的,但是主机号不能和子网中的其他主机重复。 比如:你在你家各种智能设备连接的网络,前面的若干位是一样的,后面的数字不一样,因为大家是属于同一个子网。
eg:博主手机,平板,电脑都连接同一个WiFi,它们ip地址的前16位就都是一样的
通过合理设置主机号和网络号, 就可以保证在相互连接的网络中, 每台主机的IP地址都不相同.
如何分配IP地址呢?
比如今天我们在一个大局域网里,因为我们是同一个局域网,所以网络序号都是一样的,然后只要保证主机号是不一样的就可以了。IP地址是需要被回收的,因为IP地址就是一个数字,我们有32位的IP地址,意味着全球的IP地址最多也就是2^32个,随着时代的发展,入网设备变的越来越多,早期入网设备就是一些台式机服务器,现在变成了笔记本,手机,各种智能家电...其中IP地址既然是有限的,那么IP地址就是一种资源,所以这种资源一旦被分配出去,当你不想用的时候,一定要想办法回收它。
在局域网中分配IP的两种方式:
ps:所以认为路由器只是进行路由器转发的,网络世界中的一大误解就是大家认为路由器只能进行路由转发,好多教材都说路由器只是工作在网络层的(这是因为这些教材已经老了),现在的路由器相当先进,甚至都能跑HTTP,所以现在的路由器已经俨然是一台独立的计算机了,只不过这个计算机不是给你用的,它没有显示器,没有键盘,它的输入输出就是网络,所以路由器的功能是非常强大的,路由器内部都有这DHCP动态IP地址分配的功能。
关于网络划分和建设
![]()
今天我们可以简化下模型,把学校专业当初一个整体,班级个人当成一个整体。实际上我们在学校里面会建各种群,属于同一个学院专业的人可能会在一起。比如软件的群,计科的群,经管的群...所以我现在就相当于把我们学校以两个维度的方式以学院专业作为一个整体,班级个人作为一个整体然后就划分了一个叫做网络号和主机号。网络号就相当于学院专业,只要是学院专业相同的学生就在同一个群里。主机号就相当于班级个人。每个专业群里都有一个学生会主席,每个专业的学生会主席也都拉一个群。
目前就是我们所有的不同专业的同学组成不同的群,这就是一个个局域网。每一个专业的学生会主席也组了个群,这些个专业学生会主席就可以称之为入网的路由器,所有的这些路由器也共同构成了另外一个局域网。
每一名相同学院专业的同学是在一个群里面的,每一个群就构成一个局域网,每一个学院专业都有自己的学生会主席,这些学生会主席在全校的学生会主席中自己建了个群,所以他们自组网络了。
假设我是计算机专业1班2号的学生,假设我今天捡到了一张学生卡
我看到了他的学号信息,假设我现在要归还给他,我难道是逮住一个人就去问下这个人是不是这个学生卡的主人,如果不是再接着找下一个人吗?
答案肯定不是。
查找的本质,其实就是排除的过程,当你在一个一个轮询去遍历的时候,你一次排除的只有一个,如果全校有2万人,等你找到就要猴年马月了。
所以我的做法就是搞了这样一个信息,信息内容是该学生的学号+这个学生的学生卡丢了并附上了我的联系方式;然后我就把这个消息发到了我自己的专业群里面并且@了学生会主席,通过学号辨认出这个学生不是我这个专业的,所以学生会主席就把这个消息发到了学生会主席的群里面并且@校学生会主席。因为校学生会主席和大家都熟悉,各个专业的学生会主席只认识自己的网络,但是校学生会主席就应该记录下各个学生会主席所负责的子网的网络号,所以校学生会主席认识校园所有的学院和专业,校学生会主席收到一个报文一判断,判断出这个学号是经管学院的,然后校学生会主席就@了经管学院的学生会主席,然后经管学院的学生会主席确认了一下发现确实是自己院的,然后经管学院的学生会主席就把这个报文收到了,然后发现这个学生就是田七借,接着就在经管群里@田七,田七就看见消息,发现学生卡确实丢了,然后就给我打电话。
此时我们就通过一个群内转发的方式,从一个局域网经过路由器转发到大的网络转发环境当中(其实就是公网) ,然后在大的公网当中,经过一系列转发到达田七所在的经管学院的入口路由器(经管学院的学生会主席),然后在把信息转给田七,田七就收到了这个信息。
这次就完成了一次查找的过程,其实是完成了一次数据转发的过程。
我这次查找,在路上的时候(我自己学院的学生会主席,校学生会主席,经管学院的学生会主席) 这些人只关心学号的前半部分(学院专业信息),比如:计科学院的学生会主席只看这个学号前半部分,识别到不是我们学院的,就转发到学生会主席的群里,校学生会主席也只关心学号前半部分,发现要转个经管学院的学生会主席,经管学院的学生会主席也只关心学号前半部分发现确实是自己学院的,然后把信息发到经管群。
当到达目标群(到了经管群),就只关心这个学号的后半部分(学生的班级及号码信息)。
这个学号的前半部分就叫做网络号,学号的后半部分就叫做主机号。
查找的时候,在路上的时候, 通过划分不同的群,来进行查找的。本质就是,一次可以排除1个或者多个群。刚刚我们的这种行为,将所有的学生进行编址划分成两部分(左部分是学院专业,右部分是班级个人)我们称之为网络号和主机号,另外我们把所有的网络号还要进行不同的编址,这就叫做网络划分。
网络划分本质
所以网络划分本质就是为了提高查找效率,减少查找的难度,便于组网!
所以我们对IP地址进行划分,就是网段划分的概念,不同的编号就是不同的网段,划分成不同的网段能提高效率本质就是它增加了排除的概率,一次就可以排除大部分人。
根据上面的例子,我们发现,查找的时候,在路上的时候,我们只关心目标网络,到了目标网络的时候,我们在根据目标主机找到对应的主机。所以路上找的时候全都是根据目标网络去查找的,我们可以对二进制序列做划分,然后就可以建立各种各样的群,把相同的学院专业的人放在一起。
刚刚划分的是一所学校,如果把整个地球看做成学校的话,实际上网段划分是比较复杂的与运营商组建网络有关系,我们可以把全球的网络根据IP地址,把IP的网段号划分给每个国家,然后每个国家里面可以用递归的思路进一步划分。
当然,这里只是描述下,我们其实是可以把所有的这些IP地址在全球内划分完的。我们把整个地球想象成学校的话,中国就是1号大群,我们也有很多国际路由器,这些国际路由器之间组建成大群,组建成的大群在国际上就可以进行转发。
以上只是一种草案,国际网段划分组织已经帮助我们划分好了。
分类划分法

分类划分法:
- 拿出第一个比特位,我们叫做A类,剩下的我们叫做其他,也就是第一个比特位为0就是A类,剩下的第一个比特位为1就是其他类。所以我们的网络就是A类和其他类。
- 对于B类,从第二个比特位开始,如果为0就都属于B类,剩下的就是其他;
- 对于C类,从第三个比特位开始,如果为0就属于C类,剩下的就是其他;
- 依次类推,除此之外,每一类IP还有网络号和主机号。
为什么分类要分A,B,C,D,E这样的类别呢?

- 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
为什么ip划分是这种分类划分法呢?
因为全世界的国家大小是不一样的,每个国家需要对应的IP地址的数量也是不一样的,如果是平均划分方案就是不合理的,小的国家用不完,大的过节不够用。所以分类划分可以适配不同国家的体量,让不同的国家可以拿到不同区域的网络。
再比如:我们国家拿了一个A类的,然后第一个标志位必须是0,因为是A类的,网络号是1,我们把主机号就使用20位,腾出4个比特位表示是哪个省的....如果你愿意还可以在细分,PS:这里说的ip都是公网ip。所以我们可以通过以地域的方式把ip地址也划分成一个个的大群,就好比全球是个大群,全球所有的国家对应的代表人物就参与我们全球的网络,就好比全球就是我们的学校,各个国家的代表任务就相当于专业学生会主席,他们在全球中自建一个路由器级别的网络;接下来,把我们国家又可以当成一个学校,按照省,市,区划分。实际上IP地址是可以按照地域的方式划分好的。所以,近些年我们在一些社交APP评论的时候,是可以看到评论人的地区。这是因为,这些软件可以根据你的ip地址来追溯你是属于哪里的ip,然后就知道你是谁了。
CIDR
- 例如, 申请了一个B类地址, 理论上一个子网内能允许6万5千多个主机. A类地址的子网内的主机数更多.
- 然而实际网络架设中, 不会存在一个子网内有这么多的情况. 因此大量的IP地址都被浪费掉了.
- 引入一个额外的子网掩码(subnet mask)来区分网络号和主机号;
- 子网掩码也是一个32位的正整数. 通常用一串 "0" 来结尾;
- 将IP地址和子网掩码进行 "按位与" 操作, 得到的结果就是网络号;
- 网络号和主机号的划分与这个IP地址是A类、B类还是C类无关;
eg:
所谓的子网掩码就是一串全1和全0的组合,我们可以用全1和全0的方式通过设置子网掩码当中右半部分全0的个数来限制一个局域网内主机的个数。比如子网掩码有半部分有10个0,就代表可以用的主机数是2^10个。
eg:
划分子网1
划分子网2
可见 ,IP 地址与子网掩码做与运算可以得到网络号 , 主机号从全 0 到全 1 就是子网的地址范围 ;IP 地址和子网掩码还有一种更简洁的表示方法 , 例如 140.252.20.68/24, 表示 IP 地址为 140.252.20.68, 子网掩码的高24位是 1, 也就是 255.255.255.0。
所以划分子网的方案有两种:
- 第一步是先粗力度的把全球的网络按照分类划分法分好;
- 第二步是在架设子网的时候,给每台路由器都设置上子网掩码,这样就可以通过限制子网掩码的位数来调整我对一个网络当中能够允许构建的主机数进行约束,进而不造成ip的浪费。实际上,有一个报文带着目的ip,我们是拿着目的ip和子网掩码进行按位与得到网络号,这个网络号一得到,就根据网络号进行路由转发,将报文转发到特定的区域当中。
所有的网络在全球内,每一台机器的ip不一样,这个ip我们叫做公网ip,其中我们只要保证网络号一样的放在一起就可以建各种群,一旦建好群了要对外入网 ,就必须得要路由器接通公网,路由器也是主机,我们就可以把所有的路由器组建各种的网络情况,只要大家相同的网络号在同一个主机上,我们就可以使用网络号在全国范围内进行路由查找,这个事情是可以做到的,就是由中国移动,联通,电信这样的运营商做的。
特殊的IP地址
- 将IP地址中的主机地址全部设为0, 就成为了网络号, 代表这个局域网;
例如把172.20.0.0/16用二进制表示如下:
10101100.00010100.00000000.00000000 (二进制)
将这个地址的主机部分全部改为0,则形成网络号:
10101100.00010100.00000000.00000000 (二进制)
再将这个地址用十进制表示,则为172.20.0.0。
- 将IP地址中的主机地址全部设为1, 就成为了广播地址, 用于给同一个链路中相互连接的所有主机发送数据包;
例如把172.20.0.0/16用二进制表示如下:
10101100.00010100.00000000.00000000 (二进制)
将这个地址的主机部分全部改为1,则形成广播地址:
10101100.00010100.11111111.11111111 (二进制)
再将这个地址用十进制表示,则为172.20.255.255。
- 127.*的IP地址用于本机环回(loop back)测试,通常是127.0.0.1
IP地址的数量限制
- 动态分配IP地址: 只给接入网络的设备分配IP地址. 因此同一个MAC地址的设备, 每次接入互联网中, 得到的IP地址不一定是相同的;
- NAT技术(后面会重点介绍);
- IPv6: IPv6并不是IPv4的简单升级版. 这是互不相干的两个协议, 彼此并不兼容; IPv6用16字节128位来表示一个IP地址; 但是目前IPv6还没有普及;
私有IP地址和公网IP地址
以上我们谈论的所有内容都是公网IP。
实际上,公网IP一共才42亿多,入网的主机太多太多,就比如我们的手机,电脑连接上WiFi,用的是公网IP吗?实际上用的不是公网ip。
eg:我们是有云服务器的,如果拿笔记本去ping云服务器是能联通的,但是反过来是不行的。
这是因为公网ip不够了,所有公网ip是不会给用户去用的,所有我们必须得考虑一下怎么让ip地址能够让更多人接入网络。所以我们就有了组建局域网和划分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。
eg:笔记本的ip就是私有ip
linux下主机的ip也是私网ip
这个ip是内网ip,也叫作腾讯内部组建局域网时所用的ip,你实际上想让外网访问你,你必须得用自己的公网ip地址。
全世界有很多的私网ip,这些ip够吗?
公网ip在整个公网世界是不能重复的,私有ip在自己私有网络内部也是不能重复的,比如,你家里面,你的手机的ip和你爸手机的ip绝对不一样,只要你连接的是同一个网;但是我家里的网和你家里的网和张三家里的网络都叫做局域网或者路由器给我们构建的子网,此时我们其实是可以使用同样的ip的,比如我在我家里的一台主机的ip是172.29.131.179,你有可能在你家里,也有个ip也叫作172.29.131.179。这就意味着私网ip可以在不同的子网中重复出现。所以这样的话就解决了公网ip可以给公网去使用,包括给运营商构建我们自己对应的入网设备,路由器配置的路由设备,所有想接入公网的人他只能使用私有ip,而要使用私有ip就必须得先入网,入网的时候就必须得有路由器给你构建出一个私有ip,所有全世界人类,大家在自己的局域网里面用的全部都叫做私有ip,只要大家都用的是私有ip的话,那么你的数据发出请求以及在公网中跑的时候,是由路由器帮你请求的。所以全世界人类在接入网络时,不用公有ip接公网,而是直接使用私有ip接路由器的方式来进行接入网络的。
对于运营商的理解
运营商,其中像移动,联通,电信,我们刚刚说的子网划分,子网掩码,这些网络的划分过程是由国家内部的运营商做的。人家在哪构建的基站,如何构建的局域网及局域网之间如何划分的,你都不清楚。 所以子网划分就弱化一下。对我们而言所有用户上网都用的是私有ip
你自己天天用看抖音,玩吃鸡游戏,使用各种APP...不管你是用流量也好还是用WiFi也罢,你最终交钱的时候,都是交给了运营商(移动,联通,电信)。这是为什么呢?你为什么不把钱交给这些APP呢?
根本原因在于,这些APP的公司叫做互联网公司,互联网公司实际上不是创造了一个时代,而是时代创造之下的产物。
为什么中国有这么多的互联网公司呢?
比如,非洲这样的国家就没有像抖音这样的APP。2000后,这些互联网公司才进入人们的视角,互联网公司只能是顺应时代的人,所以这一切都是因为基础设施。你家里的网,包括你的数据走在了公网中,包括你的数据转发到提供方对应的服务器里面。所以你一直走的都是运营商曾经搭建好的基础网络。从生活角度,如果你家里想开网络的话,你爸你妈必须得给移动,联通,电信其中的一家打个电话,然后就有专门的工作人员上门,把光纤引入到你家里面,然后给你安装强制解调器(也就是俗称的猫),路由器,然后把WiFi给你全部弄好,然后你才可以上网,而且你家里交网费全部都是把钱交给了移动,联通,电信。是因为三大运营商是国家的基础设施建设的缔造者,也就是说,你在门口所看到的各种基站,曾经铺设的各种光纤,还有各种企业级的交换价,路由器等各种各样的基础设施,运营商全部给你搭建好了。硬件存在之后,运营商还要和其他软件公司去合作,比如华为,去定制出自己的1G,2G,3G,4G,5G这样的通信标准,然后在硬件层面上保证你的数据能够以光电信号的形式从A端通信到B端...这些工作可不是互联网公司做的,只有运营商会做这些事情。
为什么互联网公司不做这些事情呢?
1.最简单的一点就是互联网公司是私企,三大运营商是国企。
2.互联网公司的钱,在三大运营商看来就是毛毛雨,虽然互联网公司也非常转钱,但是如果互联网公司在基础设施方面进行投入的话,它也扛不住。
3.互联网公司不愿意做这些事情,也不会愿意做这些事情,因为互联网公司都是资本催生下来的产物,如果一件事情,你投入之后,可能20年之后才能看到回报,这些互联网公司是不会做的,回报周期太长了。在比如:这些互联网公司,曾经都有很多的投资公司,投资公司最重要的就是把钱给你,短期之内就要看到利润,因为投资公司没有耐心等你20年,在拿到利润。投资公司就是要短期内的利润,然后在拿着这些利润去投资下一家的公司,投资公司快速的发展,就要快速的滚雪球,就要要求被投资的公司快速的赚钱。所以往往背后挂靠这些资本的公司特别急功近利,就是喜欢赚短钱,长期的钱虽然也能赚,但是它不想赚。万一在这个等待的时间内,你这个被投资的公司垮了就得不偿失了,风险非常大。所以只有少数的公司在资本的催生下是成功的,大部分公司在资本的催生下都倒闭了。
互联网公司不想做基础设施投入就是因为前期的投入成本太高,一次就把公司的几年利润投进去,投入之后长时间得不到收益,而且还得慢慢建设,这是互联网公司不愿意看到的。而且一旦有一家公司愿意做技术创新,愿意把公司全部的利润投入到基础研发中,推动整个行业的发展,那么这个公司是非常非常有魄力的公司,而且是需要有强力的领导人的,最具有典型代表的就是两家公司,华为与联想。大家鄙夷联想赞美华为就是大家觉得,这些公司赚了社会这么多钱,就应该去投入,去促进社会进步,促进行业的进步,可往往现实和理想总是事与愿违的,你没办法去要求人家,人家或多或少是私企。
运营商愿意去搭建基础设施吗?
所以大家都不愿意做这样的事情,当然国家不让你去碰也是有可能的,这种活只有三大运营商去干,他们愿意去干嘛?
一方面他们就是干这个事情的,从赚钱角度来看,他们也不愿意干,以前发短信打电话也得交话费,那为什么还要投入基础设施建设给你建设3G,4G网络呢?
运营商的动力也还好,但是因为国家发展的需要,所以是要大家不断进行基础设施的创新的。而且我们也都知道,我们的网络技术其实是跟着别人的步伐成长起来的,你不进步别人也在进步,所以不管是对外部的压力,还是内部的需求我们都是要推动整个事情的。所以在国家政策推动下,三大运营商就大面积的铺设基础设施网络:建基站,架设各种光纤...
运营商架设好的路线就类似于你以前想要去县城,你进不去,因为路太差了,现在有人给你把路铺好了,那么你这个人就可以去县城了,因为你可以去县城里,那么你周围的人也能都去县城了,所以去县城的人也就多了,那么那些小商小贩就可以聚合起来去做人们的生意了,小商小贩把人们的生意做起来了,然后就慢慢出现了一些大点的饭店,最后生意越做越大,于是小商小贩就喊,“是我创造了这个县城的繁荣,是我铸造了这个时代” ,现在看来,这就是笑话。
互联网公司只是时代之下的产物,如果曾经没有人修好路,那么就就不能能有人去县城,所以基础设施就是一切繁荣的前提,就和你账户余额一样,你后面有再多的0也没有意义,你必须得在前面带一个1。
所以前期投入这些事情的人是最值得鼓励的,而且前期如此投入还是有很大的风险的,就比如万一你把路修好了,但是还是没有人愿意去县城,县城就繁荣不起来,路上的人越少,你这些运营商的投入就没法回收了,不像小商小贩,前期就是花了几百块推这个车车,就到了县城,大不了没人了就不干了,损失也就是几百几千块钱,可是对于曾经把路修好的人,损失的就不是这一点半点了。
这些基础设施架设好了要不要回收成本呢?
当然需要,就事论事,这些基础设施没有运营商不行,至于后续的故事运营商内部管理混乱,乱收费现象...好的表扬,坏的使劲喷。
对我们来讲,自己上网的时候,插的是运营商的电话卡,用的是别人的4G,5G网络;家里上网的时候,交网费是交给运营商的,因为基础设施是人家干的,就应该给人家交钱。就好比:当你上高速的时候,你得交过路费,因为高速公路是人家修的,基础设施是人家建设的,人家为了回收这个成本,必须得收费,这是最简单,最直接的回收资金的方案。人家承担相应的风险高技术,即使要回收成本,甚至要获取一定的利润也是值得鼓励的,要不然谁还愿意干这些事情呢。
至于你打游戏充钱,这就是你和互联网公司的事情,就好比你到县城了与餐馆老板勾心斗角,你把钱交给餐馆老板点了很多菜,这就是你与互联网公司的事情,至于这个菜是怎么点的,就与互联网公司的商业模式是有关系的,比如:你吃饭不要钱,但是你得看10分钟广告;你吃饭交钱;你可以免费吃饭,但是你必须得去某一个地方做一件事情...互联网公司是互联网公司的玩法,但是基础设施投入的运营商的玩法就简单粗暴,我给你把路铺好,你给我交钱,就这么简单。
我可以上网的时候,不给运营商交钱,就想直接访问别人的服务器,可能吗?
完全不可能,就好比:我就不想走国道,不想走高速,凡是政府修的一切路,我都不想走,我就想走羊肠小道,从北京一直干到云南,这完全不可能。因为你手机的光电信号是不可能凭空发送到别人的服务器上的,另外你手机发送的这种视频信号其实是经过各种对应的基础设施转化的,服务器是不认识这些东西的,而且基础设施连都没连,你怎么访问服务器呢,所以你是绝对不可能绕过运营商的,你的所有的请求都必须通过运营商给你架设的基础网络,到达互联网公司对应的服务器。你绝对绕不开运营商。互联网公司同样也是三大运营商的客户,互联网公司要建机房也必须得用运营商的基础设施。所以网络背后的大佬是这些运营商,因为小白属于运营商的客户,大的互联网公司也是运营商的客户,你可能拉个几百兆的网络,互联网公司要拉的就是几百个G的光纤到自己的机房,互联网公司也是客户,你上网要交钱,这些互联网公司同样也是需要交钱的。
为什你欠了话费不能给其他人打通电话,但是你确能给运营商打通电话?
实际上,你的欠费欠的就是运营商的费用,你又没有欠互联网公司的费凭什么不让你使用网络(滑稽),因为你用的是人家互联网公司的资源,所以当你一旦欠费是运营商把你的网络掐了,你的电话号码就是你的账号,和你电话号码绑定的信息,包括费用信息都是运营商数据库里面的一张表,人家知道你欠费了,运营商就不让你上网了,说白了就是运营商不在把你发过去的报文做转发了,不给你转到互联网公司当中,那么此时你就上不了网了。但实际上你的消息其实依旧是发给了运营商的。运营商再怎么傻,也得把缴费的通道给用户打通,所以一般你是可以给10086客服打通的。
实际生活中,我们发现只要欠费了,你自己是交不了的,你必须得让你朋友交或者连上WiFi缴费,为什么移动不把这个缴费的接口放开呢?
猜测:
1.可能怕被人们吐槽,欠费了,什么都打不开,只有10086能打通,缴费能打通,这不就明摆着要钱吗。移动就吃准了你一定会想办法缴费的,反正是你主动交钱的,而不是移动问你要钱的
2.缴费也有可能和银行系统有关系,比如你交钱的时候,中国移动也有自己的移动账号,银行也属于基础设施的客户,如果你交钱交给银行的话,还是要访问外网,这可能有问题,因为你转钱的话不是把钱转给了中国移动,而是把钱转给了中国移动所在的银行账号,银行也是运营商的客户作用和互联网公司一样,你把钱交给运营商的银行账号可能也要走外网,这样做容易出问题,你欠费了只能访问银行这样也不太好,所以移动就没放开。
当然从技术角度来讲,运营商想实现欠费情况下缴费完全是可以的,只不过人家不愿意做罢了。
回顾之前的子网划分
运营商帮助我们组建了各种各样的子网,好比上述群与群转发消息的例子,计科学院和经管学院不是一个群,但是就是能把消息从计科群转发到经管群,我们两个群是没有直接相连的,但是我们有对外的路由器,我们可以把所有的路由器全部集中连接起来,这样我们就可以组成新的网络,相当于学生会主席之间的路由器可以用来数据包转发。如果你把全球想象成一所学校,我们就可以把各个国家想象成一个群,一旦建立好这个划分之后,进一步把一个国家在想象成一个学校,在一个国家里面又划分成各种省,省之间也可以在进一步的进行子网划分,一般我们常用的就是子网掩码。省划分成市,市划分成区,总之我们一定有方法把全球的地区都覆盖上对应的网络,这是可以做到的。
我们经过这样的不断向下划分后,各个地区的网络是有它自己的一部分区域覆盖的,比如:你家附近就有一个专门的运营商小店帮助你联网,当客户想上网的时候,就把网络拉倒客户的家里面,当我们的这些运营商把网线拉倒你家里的时候,背靠的就是整个网络的基础设施
实际上不要把运营商认为是一个帮助我们转发数据的,运营商也有自己配置子网的一些方式,其中也有自己各种企业级的交换价或者路由器。
比如:
ip为122.77.241.3就是给我们提供服务的服务器(比如说是抖音的服务器),上图中的电脑设备就是我们用户。我们每一个人要上网的时候,首先给移动打电话,移动就派一名工作人员过来,给你拉好网线,安装强制解调器,安装家用路由器。路由器的密码是有两套的,第一套是给用户的,就是你家的WIFI密码,第二个就是这个路由器内部需要设置一下你的缴费账号,通过这个账号信息去认证你。
路由器是可以用来组建局域网的!不光是你的家用路由器,运营商的大型路由器也是可以组建的。运营商路由器之间构建的网络就是公网。这个运营商路由器最大的意义管理它旗下的路由器,当用户请求的时候,可以把你的请求给转发出去。
eg:手机是可以上网的,你可以把你的手机热点打开,然后让你周围的同学连接上你的热点去进行上网。把你的手机热点打开就是把你的手机当成一部路由器,组建了一个局域网,让你的朋友去上网,上网的时候,你的朋友用你的热点就是把数据发到你的手机上,通过你手机的路由功能,再把数据发出去,这就是一个构建子网的过程。所以路由器只要能不断的去构建子网,网站在基础设施建设就可以把子网不断的去细分。
一般的家用路由器或者运营商路由器都会配置上两个完全不同的ip,因为一个路由器要转发报文,就必须得横跨至少两个网络:
- 路由器对内的ip叫做子网ip也叫LAN口ip;
- 对外的ip就叫做WAN口ip;
运营商路由器的WAN口ip很明显就是公网ip了,我们就可以通过它把消息转发到其他网络。换句话说这里的运营商路由器可以让用户把数据通过公网转发到服务器。实际上,运营商再牛,也不可能把基础设施架设到美国去。其实国家和国家这个广域网之间,我们也是要通过一些国际的线路去互相联通的。
所以对我们来讲,企业就可以将自己的信息接入到公网当中,用户通过自己的私有ip也能接入到公网当中,此时用户就可以直接去上网了。当然,企业接入公网的时候,很多的主机甚至都是公网ip。
总结:
1.所有的用户对应的信息是在家用路由器当中以局域网的形式接入网络的。
2.每个路由器都有自己的LAN口(子网ip)和自己的WAN口。
3.路由器是可以构建子网的。
4.当运营商把基础设施构建好后,互联网公司要接入,就可以直接把自己的若干台机器接入到公网之中,背靠的也是自己内部的机房,只有少量机器是可以入公网的。将来你的客户请求都是要通过这些基础设施转发的。
客户的一个请求是如何转发给另外一个客户的呢?
比如我想搜索,我怎么把我的请求转发给百度呢?
我拿我的192.168.1.201经过报文转发交给家用路由器,这台家用路由器可以看到我的目的ip一定填写的是百度的公网ip,家用路由器在做路由查找的时候发现,你不想再局域网内转发,这个目的ip和家用路由器的子网掩码做按位与,发现目的ip的网络和家用路由器的局域网不一样,就转发出给运营商路由器,运营商路由器又帮助我们在公网中,找到百度的公网ip。此时百度就收到了源ip是192.168.1.201,目的ip是122.77.241.3这样的一个报文,百度收到了,就会根据你的要求构建一个响应,但是构建响应的时候就出现问题了。因为百度构建响应的ip就是192.168.1.201,可是这个ip是私网ip,全网中这个ip是可以重复的,百度也就无法把这个报文给你响应回来,就是因为私网ip不具有唯一性。
这个时候,运营商就出现了,当你请求的时候,你请求的目的ip一定是122.77.241.3,你的源ip是 192.168.1.201,当你把你的请求发送到对应的家用路由器的时候,此时家用路由器会做一个工作,会把你的源ip替换成家用路由器的WAN口ip,就是10.1.1.2(当然也有可能把你的端口号也替换调),当家用路由器转发给运营商路由器的时候就如同这个报文是家用路由器产生的一般。当交给运营商路由器的时候,运营商在把这个报文的源ip替换成运营商路由器的WAN口ip122.77.241.4替换完毕之后,此时到达公网的这个报文的源ip就是公网ip了,然后百度收到这样的请求,就认为是这个运营商路由器发来的,所以百度收到请求后构建响应,然后就把响应报文返回给运营商路由器。
所以,我们自己的请求在对外发送的时候,我们的源ip地址可能一直在被中间路由器替换,这样的技术我们称之为NAT技术。
那么现在构建响应回来,如何把数据准确的响应给用户呢?
稍后回答。
为什么私有ip不能出现在公网上?
路由器既能构建子网,又能分配ip,还能做地址转化。这也就是为什么这些私有ip不能出现在公网上,不是不能,而是不可能,因为你想要上网就必须得走运营商,运营商所有的路由器包括你自己的家用路由器都得给你做地址转化,所有凡是公网上的报文是不可能出现私有ip的。
我能不能直接把消息转发给我的朋友呢?
我想把我的数据直接通过运营商路由器去转发,而不经过公网,这能做到吗?
从技术角度是可以做到的,但是常规情况下,这种方式是不可能的,因为我们两个的ip地址都一样,你想要把数据通过家用家用路由器转发给朋友是不可能的,虽然路由器是会给我们做ip地址转化的,运营商路由器也确实可以把报文通过你家的路由器转发到你朋友家的路由器上,但难点就是怎么让家用路由器把这个请求交给你的朋友。
大部分情况下,不同子网的两个人想直接通信的难度比较大一些,不是不可能,也是有方法的,从技术角度实现也还行,关键是我们两个要直接通信,最好还是要经过公网去通信。
正常情况下,你要和我通信,说白了就是你的软件和我的软件通信,所以对我们来讲,大部分情况下的工作方式就是你自己写个客户端,把你的数据放在云服务器,另外一个客户端也是连上云服务器,从云服务器上拿数据,所以我们两个要通信,实际上是要通过云服务器做数据交换的。
有些技术是不需要通过云服务器做交换的,比如有些下载服务,eg:快播 (时代的眼泪),包括很多的软件如果进行下载走公网太慢,也可能会做一些发现技术。
总之,一个局域网不经过公网到另一个局域网这种情况从技术理论上是可以的。
浅谈墙
比如你欠费了运营商就不让你上公网了,这就意味着运营商是可以拦截你的请求的,我欠费只是一个条件,就比如如果我没欠费,我想做其他事情,运营商也是有可能拦截我们的,我们经常说我们国家的网络是有墙的,我们访问外网要翻墙。你自己的一些请求不太合法的话,运营商是有能力拦截你的,所以我们经常说的墙是三大运营商手拉手构建起来的,说白了就是当你的一个请求当中涵盖了非法的请求时,运营商内部也会做各种甄别,换句话说,不要认为你天天访问某些网站的时候,别人是不知道的,运营商一定要对你的数据做检测的,它要知道你访问的网址是不是合法的,是国内的还是国外的。所以运营商对你的请求做检测,如果检测到你的请求是非法的,那么运营商直接就把你的报文在自己的基础设施这一层直接给你丢弃掉,一旦把你的请求丢弃掉,就出现了你访问的网络不可求,所以墙就是在运营商基础设施里面,相当于三大运营商给我们构建起来的信息屏障。对我们来讲,运营商构建起来的信息长城拦住了我不让我去访问外网,同样的拦住你的同时,也拦住了别人,外网想访问我们,也必须得想办法穿过运营商的基础设施。
运营商的拦截策略有很多,就比如你想访问谷歌是访问不了的,你的请求的时候首先要拿到谷歌的域名,人家解析不了这个域名就访问不了,即便你解析了,一旦发现这个ip是谷歌的,人家也不让你访问。所以运营商可以通过你访问的网址,ip信息去拦截你,识别到你文本信息内包含国外的网址话,就直接把你给丢弃掉了。此时你也就看不到响应。当然,也是有可能绕过他们的。
国内的互联网公司为什么不去国际上呢?
一方面因为国际上竞争能力强,主要方面还是因为基础设施,如果非洲的经济能跟上,基础设施起来了,那么这些互联网公司都是会产生的。中国,美国这样的国家就给落后地区打了个样,落后地区怎么发展,就是参考先发展国家走的路。非洲这样的地区,它的基础设施没跟上,所以先过去的就是手机,笔记本,台式机..尤其是手机,过去的更多是传音手机这样的,主要进行打电话,拍照。等他们基础设施起来的时候,一定会有3G,4G这样的手机过去的。
路由
在复杂的网络结构中, 找出一条通往终点的路线;
IP数据包的传输过程
- 1.大爷听到你要去北理工,他如果知道,他就会在自己的脑海里搜索,然后就告诉你,眼中这条路直走100米,然后有个汽车站,然后你再去问下在那里等车的人,那些人就经常去北理工,你问下他们吧。所以这个大爷就告诉了我们一个答案,你现在应该下一跳去哪里,也就是告诉你下一跳路由应该去哪里。
- 2大爷思考了一下,说我也不知道,但是你看到那个大妈没,那个大妈对路熟得很,我不知道去北理工的路应该怎么走,但是我知道这个大妈肯定是知道去北理工的路怎么走,所以你去问大妈吧。这种结果就是大爷不知道该怎么走,但是大爷知道谁可以帮助你,就把你转发到了另外一个路由器。
- 3.此时大爷上下打量了你一番,大爷亮出一块牌子,上面写的是北京理工大学,这个大爷是北理工的保安,大爷就告诉你,同学不用在找了,这就是北理工的门口。其中对你来讲,虽然你已经到了北理工,但是你的路由还没完,所以我此时就紧接着又问大爷,“18号宿舍楼该怎么走”,大爷就告诉你沿这个路直走,直走之后,上面有楼号,你就看见了。此时你便顺利的到达了北理工,并且顺利的到达了18号楼。
- 第一种情况就是大爷知道下一跳怎么走,这叫做你的数据包经过大爷思考的过程就是根据你的目标地址,做了一次路径查找,思考完之后得到的结论就是下一跳应该去哪里。
- 第二种情况就是大爷不知道下一站应该去哪个路由器,但是大爷知道如果自己查不出来,此时就应该跳转到下一跳叫做默认路由器。所以第二种查找结果就是问了一个大妈,如果查路由表没查到,每一个路由器都配有自己的默认下一跳。
- 第三种情况我们就称之为你所要去的目标网络的入口路由器,在你没有达到入口路由器之前,你在进行路径转发的时候,你最常规的就是得到两种答案,一种下一跳应该去哪一个,第二种默认路由。
所以对我们来讲,实际在进行根据目的ip去做路径查找的时候,我们是先根据目的ip地址,先根据目标网络,先找到目标网络,然后再根据目标网络所对应的入口路由器,再将我们的报文进行内网转发到达目标主机,这是路由的宏观思路。
- 当IP数据包, 到达路由器时, 路由器会先查看目的IP;
- 路由器决定这个数据包是能直接发送给目标主机, 还是需要发送给下一个路由器;发送给下一个路由器有两种情况1.转发给的下一跳路由器是明确的 2.查完之后没有,只能把你放到下一跳
- 依次反复, 一直到达目标IP地址。然后就进行所谓的内网转发
为什么我经过不断的去查找路由表,直接就可以不断的去跳转到下一跳,然后找到目标网络呢?
1.首先路由表的建立,路由表的条目肯定是让我们查找的范围越来越小的。
2.我们不断在查找的过程中,当时人家在做网络建设的时候,已经给我们把各个片区划分好了,中间的路由器自己的路由条目是支持我们从一个区域跳转到另外一个区域的,这是能做到的,所以我们不断的跳转下一跳的过程就是不断靠近目标子网的过程。
全球有很多的子网,你每次一跳转到下一个路由器就意味着你放弃了当前你所处的子网,也就是你排除了一个子网,你不断在查找的时候,就是所有的子网不断被排除的过程,这样最终你总是会找到你想去的子网的。实际上这个与我们的网络建设是有很大关系的,从一个局域网出来的数据是会被扔到我们对应的路由器构建的子网当中的,在路由器内,因为路由表已经构建好,每个路由器都认识路径的全貌,所以路由器就可以进行路径转发。
那么如何判定当前这个数据包该发送到哪里呢?
这个就依靠每个节点内部维护一个路由表
eg1:我们在云服务器上的route命令,就显示出OS维护的路由表
- Destination:就代表路由器直接连接的目标子网
- Gateway:表示路由器
- Genmask:叫做子网掩码
- Flags: U表示它当前正在被使用,G表示这个东西是个路由器
- Iface:代表路由器所对应的接口,因为我们今天是一台服务器,所以它的接口只有一个。实际上路由器至少两接口,要不然路由器怎么配两个ip,连接两个网络呢。Iface的意思就是说,将来你可以通过这个接口来收发数据。
比如我有一个要去10.0.8.3这个ip的报文被我这台路由器收到了,然后就去查路由表。因为表里面有2条记录,我就拿着这个ip地址和任意一个条目配置的子网掩码(子网掩码的长短就设置了子网,路由器就是根据子网掩码构建的子网)按位与,此时就得到了10.0.8.0 这样的目标网络,然后和Destination做对比,发现要去的就是这个目标网络,然后就直接把你这个报文通过eth0这个接口扔出去,此时就完成了一次路由表的查找。
如果是要去127.17.0.2这个ip的报文被我这台路由器收到了,还是分别与这2个条目作对比,查完路由表发现你的目的网络经过子网掩码按位与并没有匹配的Destination,最后我们直接就default,此时我们就可以直接把这个报文扔给默认下一跳了。
这个例子没有体现出来我下一跳应该去哪个路由器的问题,因为这个路由器是家用级别的一个路由器,如果是在运营商内部的一些路由器,它是要帮你完成各种数据包转发的。比如说,有可能运营商在判断的时候,它就知道你一定是要把数据转发到公网当中,但是有时候我们在运营商内部就是想把数据转发到另外一台主机,虽然这种技术难实现,但是这种技术确实可能存在。所以运营商在做路由查找的时候做判断,你要去的目标网络如果是外网,虽然我不知道你要去哪个外网,但是我知道你不是我本主机,所以我就直接把你扔到我的路由器了,如果你要内网当中,我就要把你转发到下一跳另外一个子网的入口路由器当中。
eg2:假设某主机上的网络接口配置和路由表如下:
- 这台主机有两个网络接口,一个网络接口连到192.168.10.0/24网络,另一个网络接口连到 192.168.56.0/24网络;
- 路由表的Destination是目的网络地址,Genmask是子网掩码,Gateway是下一跳地址,Iface是发送接 口,Flags中的U标志表示此条目有效(可以禁用某些 条目),G标志表示此条目的下一跳地址是某个路由器的地址,没有G标志的条目表示目的网络地址是与本机接口直接相连的网络,不必经路由器转发;
- Geteway中打星号的就是一个网络,如果是具体ip或者是default这种的就代表默认路由对应的下一个设备。
转发过程例 1: 如果要发送的数据包的目的地址是 192.168.56.3
- 跟第一行的子网掩码做与运算得 到192.168.56.0,与第一行的目的网络地址不符
- 再跟第二行的子网掩码做与运算得 到192.168.56.0,正是第二行的目的网络地址,因此从eth1接口发送出去;
- 由于192.168.56.0/24正 是与eth1 接口直接相连的网络,因此可以直接发到目的主机,不需要经路由器转发;
转发过程例 2: 如果要发送的数据包的目的地址是 202.10.1.2
- 依次和路由表前几项进行对比, 发现都不匹配;
- 按缺省路由条目, 从eth0接口发出去, 发往192.168.10.1路由器;
- 由192.168.10.1路由器根据它的路由表决定下一跳地址;
所以对我们来讲,路由表查找的过程实际上是根据路由表的条目来一个一个做转发的,这个时候,我们在重新回过头,以下图为例:
当你发起请求时(目的ip是122.77.241.3),你自己的OS也有路由表,然后拿着目的ip和去查当前OS的路由表,发现这个报文要去的目标主机根本不在我这个局域网上,然后就直接可以交给家用路由器,家用路由器也可以自己做路由表查找,然后再做路由,你要去的目标网络还不在当前主机,就把他扔给运营商路由器,在广域网当中还有可能有很多很多的中间路由器,比如跨区的,跨省的,跨国的...经过转发找到目标路由器。本质上每一个过程都是查路由表的过程。
当然路由表在构建的时候肯定也不是随便构建的,我们的网络是经过精心设计的,只要一个报文在不断的对外转发的时候,它一定是无限性的趋近于自己的目标网络的。
ps:目的ip是127.0.0.0本地环回,这样的报文实际上是不会经过网络的,它实际上是把协议栈走了一圈,向从上到下交付了一下,到了网络层这,就查自己的路由表,发现就是给自己的,然后自己就把报文自底向上交付了,所以它其实没有转发,没有发就体现在它其实是没有把数据交付给数据链路层的。
路由表生成算法
数据链路层
对比理解 "数据链路层" 和 "网络层"
目前我们已经有了一种把数据经过网络,经过路径选择,将数据跨网络传送到B主机的能力,它是通过子网划分,运营商进行网络建设,路由表构建网络,以及报文根据目的网络进行路径查找,综合给我们提供的这种能力,让我们能够把报文经过路径转发送到主机B,我们的ip不提供可靠性,因为报文丢失了不担心,因为ip头上就是TCP,一旦ip失败了,长时间得不到应答,那么TCP就会直接重发刚刚的报文,对应的就是ip报文被重发了;因为ip具有这种能力的意义就在于它有较大的概率将数据发送到主机B,所以如果我们丢包了,没关系,重传一下就可以了,这就叫做TCP/IP综合的提供了这样的能力。
ip最重大的意义,在于路径选择!!!
ip最大的意义不在于报文一个个的转发,而在于路径选择,查路由表的过程,实际上是在进行路上决策,我们应该要把我们的报文转到下一跳还是怎么样,解决的是路径选择的问题,就好比我们的ip提供了把数据包转发过去这样的能力,但是要把数据从主机B到达主机C,这个是ip层给我们提供的一个跨网络传输的能力,但是ip要把数据从主机A到C,你得先经过路由选择先把数据从A交给路由器A,然后再交给路由器B,再到C,再到D,经过一跳一跳转发才能到达主机C。
你为什么要把数据包由路由器A交给路由器B呢?
这是由目的ip决定的,目的ip是由目的网络和目标主机构成。
如何把数据包由路由器A转到路由器B呢?
数据链路层解决的!
ip最大的意义在于,经过每个路由器的时候,进行路径选择的时候,是ip负责的,而把报文经过决策之后,要跳转到下一跳,如何跳转是Mac帧决定的,为什么要跳转是ip决定的。
TCP+IP+MAC帧每一层起的是不一样的作用,TCP保证可靠的把数据转到对面,ip给你提供路由的能力,让你能做路上的决策,数据链路层给你提供路上把一个报文转到下一个报文的能力。然后我们就具备了将一个数据可靠的从一端送到另外一端的能力。
凡是能够跳转到下一跳一定是直接相连的节点!直接连接的节点一定是在同一个网段(局域网)。所谓的网络就是无数个局域网,通过一些横跨局域网的路由器连接起来的大网络。所以所谓的路由转发的本质就是将数据包从一个局域网不断经历中间若干个各种局域网的过程。
我们接下来研究的就是局域网通信的问题!!!
同一个局域网,两台节点能直接通信吗?
当然能。
eg:博主的手机和电脑连接同一个局域网进行互传文件(依靠手机端的远程连接功能)
因为电脑和PC都连接的校园网,属于同一局域网,所以他俩可以进行通信。
如果手机用流量,电脑用WiFi,此时他俩就不在同一局域网了,也就不能进行通信了
局域网通信
局域网通信常见的有:以太网或者令牌环网。博主重点讲解以太网,之后提到的局域网都是以太网
以太网的通信原理
在同一个局域网,任何一个时刻,每台主机都是首先连接的我们对应的局域网,你可以把局域网相想象成一根大的网线,把所有的主机都连接起来了,一个主机想给另外一个主机发消息,直接就把资源扔到这个网线上就可以了,这个资源当中的数据是被所有的主机全部都能收到的,所有主机全部收到了,但是所有的主机会对比自己主机的Mac地址,发现数据填充的Mac地址不是自己的,所有主机都会丢弃,只有目标主机会接收,此时目标主机就收到了这个数据,此时就完成了一次单向转发。局域网的这块网络资源是被所有主机全共享的,意味着我们不允许多台主机同时向网络中发消息,此时就有了碰撞检测,碰撞避免算法,来保证任何时刻只允许有一个人向局域网中发数据。换言之,以太网的通信标准是通过概率,通过尝试去进行的。
局域网是通过碰撞检测和碰撞避免完成的,我们一般把这个局域网就叫做碰撞域,如果你想黑掉这个局域网,无非就是向局域网里塞垃圾数据。
以太网帧格式
网络协议是分层的,最顶层是应用层,然后是传输层,网络层,数据链路层。应用层产生一个数据是会添加自己的报头的,向下交付给传输层,传输层加上自己的报头,向下交付给网络层,网络层在添加自己的报头向下交付给数据链路层。数据链路层再添加自己的报头,最后形成的这个玩意我们称之为数据帧。
- 源地址和目的地址是指网卡的硬件地址(也叫MAC地址), 长度是48位,是在网卡出厂时固化的;
- 帧协议类型字段有三种值,分别对应IP、ARP、RARP;
- 帧末尾是CRC校验码
之前我们讨论分片的时候说过,Mac帧要求上层传送的数据包不能太大,规定就是1500字节,数据包太大就要求分片,哪怕分多次发,也不能太长。网络层交付的整个ip报文整个就会全部包裹在数据帧的有效载荷当中,在数据链路层,这整个ip报文就被称之为数据了。
如何分离报头和有效载荷(封装)?
因为它采用的是6+6+2 结尾+4。
所以头部加14个字节,尾部+4个字节的数据就完成了封装。
解包的话就是定长的报头。18字节。
如何决定将自己的有效载荷交付给上一层?
通过类型字段来决定。
认识MAC地址
在局域网中转发数据的时候,一旦决定了我下一跳要去哪里,那么ip就没有意义了,接下来我们在局域网转发的时候,我们就叫做如何把数据包转发给下一跳,我们用的就是在同一个局域网中对应的MAC地址。
MAC地址是48位
ether代表以太的意思,点分十六进制的风格,就是48个比特位。MAC地址是在网卡当中已经内嵌好的,是网卡厂商在出厂的时候已经帮我们把对应的MAC地址已经写好了,所以每个主机都有唯一的标识符来标识该主机。
所以数据帧中目的地址指的就是目的Mac地址,就是6个字节。源MAC地址代表的就是这个地址是哪个主机发的。它俩就代表这个数据帧是哪一个主机发的,要发给哪一个主机。
类型字段
类型字段决定我的这个有效载荷里装的是什么;
有点像邮寄包裹的时候贴的一张纸,写的是易碎物品,轻拿轻放,它就告诉我包裹里面装的数据类型。
- 如果这个里面填的是0800(16进制的写法)就叫做里面的类型是ip数据包。
- 其实在数据链路层之上,网络层之下,其实也是在链路层,它上面还有一些有用于管理的协议,叫做ARP协议,所以数据链路层既可以把数据包交给网络层,也可以了交给同层当中它的数据帧上一层的协议,叫做ARP协议。
- 0806代表的就是ARP;
- 8035代表的就是RARP。
类型决定有效载荷是什么,我就可以根据类型决定将我的有效载荷是交给上层的ip还是交给ARP协议。
CRC校验字段
CRC校验字段:就是在一个偏硬件的程度上,来对我们所谓的数据进行相关的校验工作。这个校验工作通常是看我们的数据帧有没有问题,比如比特位翻转或者发送碰撞出现错乱的问题。
再谈局域网
局域网通信能力的存在是为了支持跨网络转发的,也就是支持ip的,ip要能够跨网络转发到目标主机又是为了支持TCP进行可靠性保证的。这些所有的过程都叫做通信细节。
eg:局域网转发过程
主机A的Mac地址是MA,主机B的Mac的地址是MB(假设主机B就是路由器)。他们两个要通信,一个ip报文下达到主机A,然后就在数据链路层开始转发,主机A的数据帧,类型这里填0800,目的Mac地址填写的就是MB,源Mac地址就是MA,数据有效载荷就是ip报文。然后我就把这个数据帧扔到网络里面了,接下来你就应该把数据交给物理层,所以实际上开始的就是硬件的操作。然后这个局域网里所有的主机都能收到数据帧,大家收到的时候,每一个人都要先进行解包,提取目的地址,发现是MB,所以除B主机外的所有主机在自己的Mac帧层就丢弃了。每一台主机都有自己的协议栈,拿到数据的是协议栈最底层的数据链路层拿到的,拿到之后对比自己的Mac帧发现不是就直接丢了,报文丢弃了,也不会向上交付。所以除B主机外的所有主机压根就不知道自己曾经收过这个数据帧。B路由器收到数据进行解包发现目的地址和自己相等,然后根据类型发现是0800,然后将自己的数据交给网络层,因为它自己是给路由器所以就不在解包了,然后自己提取出数据中的路由的目的ip,查路由表,发现这个东西要到下一跳了,下一跳又是一个节点到另外一个节点,然后又要向下交付,然后就重新再次封装Mac帧,然后再交给下一跳路由器。这就叫做局域网的通信。所以局域网的通信根据Mac帧做目的地址对比就可以了。
只有有了局域网的技术,才可以将所有的局域网集联起来构成广域网,所以所谓的路由转发,无非就是决策将数据从一个局域网转发到另外一个局域网,因为路由器的存在它可以调节至少两个网络,网络里存在大量的路由器,那么大量的局域网就被连接起来了。实际上无线LAN和令牌环已经不重要了,因为有ip地址的存在,所以实际上就可以屏蔽掉底层网络的差异,统一使用ip地址。路由表在路由的时候一定经历了一次解包和重新封装的过程,路由器有两个网络接口,左侧是以太网,右侧是令牌环不影响,因为路由器一定既装了以太网的驱动程序,又装了令牌环网的驱动程序,所以当他解包时是按照以太网进行解包的,当他路由之后知道我要跳转到下一跳,重新去封包的时候, 因为另一个接口接的是令牌环网,所以它封的肯定是令牌环的报头。所以站在网络层网上看,所有的网络都没有差异,全都是ip网络。
有效载荷
以太网的数据帧的有效载荷最少不少于46字节,最多不超过1500字节。如果有效载荷太少的话,我要给你添加pad,pad叫做填充,意思就是随便给你加的值,只要凑够46以上就可以。因为传送太少的话可能会出现问题。
在局域网中做数据转发的时候是基于碰撞检查,碰撞域这样的策略去做的,所以为什么数据帧的物理层为什么要规定1500字节?(虽然这个值可以改大也可以改小,但是基本上都是1500)
如果不规定上限的话,我们的数据帧可以很大,很大的时候,意味着上层就可以交下来很大的数据,也就意味着主机发送的数据帧可能会很长,数据帧很长的话也就意味着在物理层光电信号发送的时候它可能需要较多的时间,那么就意味着一个数据帧在网络里进行转发的时候,它占据的一个单位时间就会变的长了,在单位时间内变长,就可能增加局域网冲突的概念,所以数据帧一定是尽快发送。别人没有发送数据的间隙肯定是比较短的,时间越短,其中你可发的数据量就越少,要不然就冲突了。所以数据帧有上限,一定是根据对应的硬件考量实验出来的,所以一定需要我们遵守。不要认为1500就是慢,如果是1500以上,那么一旦出现了拥塞,丢包,那么你重传的量也大,所以不能无脑增大,要考虑全面。
认识MAC地址
- MAC地址用来识别数据链路层中相连的节点;
- 长度为48位, 及6个字节. 一般用16进制数字加上冒号的形式来表示(例如: 08:00:27:03:fb:19)
- 在网卡出厂时就确定了, Mac地址是内嵌在网卡当中的,Mac地址是网卡当中的某一种序列化,只要保证网卡中Mac地址不重复就可以了,不能修改. mac地址通常是唯一的,注意这里的全球唯一指的是真实的硬件,也有一些技术可以虚拟出Mac地址,比如虚拟机可以虚拟出设置一些网卡。所以你想伪造一个网卡,在局域网中也是可以的,因为Mac地址根本不会跨网络传送,你这个Mac地址只在你的 局域网中可以被其他的主机采纳使用,一般不会跨网络传送,所以我们伪造的时候只要和别人不一样就可以了(虚拟机中的mac地址不是真实的mac地址, 可能会冲突; 也有些网卡支持用户配置mac地址).
对比理解MAC地址和IP地址
- IP地址描述的是路途总体的 起点 和 终点;
- MAC地址描述的是路途上的每一个区间的起点和终点;
认识MTU
MTU相当于发快递时对包裹尺寸的限制. 这个限制是不同的数据链路对应的物理层, 产生的限制.
- 以太网帧中的数据长度规定最小46字节,最大1500字节,ARP数据包的长度不够46字节,要在后面补填充位;
- 最大值1500称为以太网的最大传输单元(MTU),不同的网络类型有不同的MTU;
- 如果一个数据包(ip层,每个层的报文有不同的名字)从以太网路由到拨号链路上,数据包长度大于拨号链路的MTU了,则需要对数据包进行分片(fragmentation);
为什么不让数据帧做分片呢?
如果数据帧做分片,那么报头就得改,数据帧配套的协议就得改,协议改了,驱动就得改,驱动改了,那么硬件就有可能也要变。我们肯定是更愿意去改软件。所以多我们来讲我们把他交给网络层让ip去改可以说是众望所归。
- 不同的数据链路层标准的MTU是不同的;
强制解调器是什么呢?
我们一般在局域网中通信的时候,是有很多的数字信号或者模拟信号,比如说数字信号,在运营商发的时候,是需要经过我们所谓的强制解调器把数字信号到模拟信号进行互相转化的,因为在硬件传播上是有差别的,强制解调器就是做这个事情的。
MTU对IP协议的影响
- 将较大的IP包分成多个小包, 并给每个小包打上标签;
- 每个小包IP协议头的 16位标识(id) 都是相同的;
- 每个小包的IP协议头的3位标志字段中, 第2位置为0, 表示允许分片, 第3位来表示结束标记(当前是否是最后一个小包, 是的话置为1, 否则置为0);
- 到达对端时再将这些小包, 会按顺序重组, 拼装到一起返回给传输层;
- 一旦这些小包中任意一个小包丢失, 接收端的重组就会失败. 但是IP层不会负责重新传输数据
曾经我们讨论分片的时候是以端到端(从自己的主机到对方的主机)的方式去讨论的。 因为这是最简单的,实际上我们现在就知道了,当我们的数据包在路由转发的时候,你的主机规定是1500,它的主机规定也是1500,我经过的路上的路由器,有可能路上的路由器本身的mtu可能就是500,所以在你主机经过路由器转发的时候,进来是1个报文,出去就可能是3个报文了,所以在路上也有可能分片。
如果在路上分片了,接收端主机该如何合并呢?
不要担心,最关键的就是13位片偏移,如果你的报文,在路上也片偏移了,原始的报文有原始的片偏移,如果你再分片,我给他分片的子分片偏移量+我曾经的片偏移,那么子的片偏移量就不是0。所以,虽然报文变得很细,但是每一片采用的片偏移依旧是在原始当中的片偏移位置。
eg:
分片的过程上层协议不关心,也不知道。一旦过多分片,就有可能导致丢包的概率增加。
MTU对UDP协议的影响
- 一旦UDP携带的数据超过1472(1500 - 20(IP首部) - 8(UDP首部)), 那么就会在网络层分成多个IP数据报.
- 这多个IP数据报有任意一个丢失, 都会引起接收端网络层重组失败. 那么这就意味着, 如果UDP数据报在网络层被分片, 整个数据被丢失的概率就大大增加了.
MTU对于TCP协议的影响
- TCP的一个数据报也不能无限大, 还是受制于MTU. TCP的单个数据报的最大消息长度, 称为MSS(Max Segment Size);
- TCP在建立连接的过程中, 通信双方会进行MSS协商.
- 最理想的情况下, MSS的值正好是在IP不会被分片处理的最大长度(这个长度仍然是受制于数据链路层的MTU).
- 双方在发送SYN的时候会在TCP头部写入自己能支持的MSS值.
- 然后双方得知对方的MSS值之后, 选择较小的作为最终MSS.
- MSS的值就是在TCP首部的40字节变长选项中(kind=2);
我们来算算:
数据链路层规定1500,我们不考虑携带选项这样的概念,也就意味着会影响网络层,网络层的标准报头20自己,所以网络层的有效载荷就是1480。TCP的标准报头也是20个字节,也就要求传输层有效载荷只能是1460。传输层的1460就是用户交付给的字节数。换句话说:应用层定义了1M数据,一次就通过send发出去,实际上你把数据全部拷贝到TCP的发送缓冲区里,你以为你发了1M实际上TCP不可能一次把1M全部发出去,他只能1460,1460...一个一个的包裹进报文经过数据链路层转发出去。
所以,应用层叫做用户,下三层叫做内核层,内核处理通信细节,用户不关心。
路由器如何跳转到下一跳
在进行路由转发的时候实际上是把数据从一个局域网交个另外一个局域网,通过一个子网交给下一个子网,子网和子网间跳转是通过路由器,因为路由器至少连接两个子网。子网之间的关系是由运营商划分好的。
如果这个数据包跳转到目标子网的入口路由器,因为路由器D和主机B是属于同一个局域网的,属于同一个局域网把数据从路由器D交给主机B是要封装mac帧的,所以我们就得需要知道对方的目的以太网地址的,但是目前这个数据包被路由器D收到了,但这数据只知道要去的主机的目标地址是ipB,但是这个报文里并不涵盖你要去的主机B的mac地址,而且路由器D也不能确定当前的这个ipB它对应的mac地址是谁,也就是说路由器D只知道这个报文的目的ip,而要把这个数据包交给主机B,就必须得知道它的mac地址,因为我们要封装Mac帧。怎么办呢?
直接进行广播,在局域网中要进行局域网广播,只需要将以太网目的地址设置成全f,那么这个数据帧就会被局域网内的所有主机收到,这就是广播。可是广播不准确,你只想发给主机B。再者广播给所有人是会影响别人的。
当然广播之后到达ip层对比ip地址,如果不对了就直接在ip层丢弃,看起来好像可以,但是实际上我们并没有这么干。比如:你的路由器积压了很多报文都是发给主机B的,可是主机B被拔网线了,然后路由器分配地址的时候,把主机B曾经的地址分配给主机A了,这个时候路由器曾经积压的数据就全部发给主机A了。这就有问题了。
广播缺点:广播方式会产生大量流量,导致带宽利用率降低,进而影响整个网络的性能。
当需要网络中的所有主机都能接收到相同的信息并进行处理的情况下,通常会使用广播方式。
现在的问题是,你把这个报文转发过来,可是你只知道这个报文要去的目标主机ip,而你要把数据单向的交给主机B,你必须得有对方的mac地址。
ARP协议
如何在网段中,通过ip地址,获得该主机对应的mac地址
我们就需要一种ARP协议,叫做地址转化协议,是把你要的ip地址,转化成对应的mac地址
ARP协议就是一个在局域网内发现每一台主机对应的Mac地址的一个通信协议。
eg:今天老师还是在教室上课,老师现在不知道有一名同学叫张三,但是老师知道每一名同学的学号,今天老师想和学号是10号的同学进行聊一聊,老师就说,10号同学,请你告诉我你的名字。此时这条消息在教室的所有同学都听到了,大家里面就在对比着自己的学号,最后只有学号是10号的同学站起来了,就说,老师我是10号,我的名字叫张三。老师就知道了10号的名字,从此以后老师就不在叫他10号了,而是直接叫他的名字张三。同理,老师就可以通过这种方式,知道其他学号学生的名字了。所以老师知道学生的学号,就可以通过学号的方式来首先获得同学的名字。换句话说,老师知道的同学们的学号,就相当于在局域网内同学们的ip地址,知道了同学的ip地址,就可以通过ip交换你的Mac帧。其中交换原理,就是我先拿着你的ip进行广播,我们子网中谁是10号主机?
因为是广播信息,所有主机都要收到这个信息,并解包,并且都要处理;处理之后,向上交付的时候,如果发现这个信息包含的请求的ip地址不是我,就直接丢弃。如果是我,就进行保留,然后再给目标主机单向的发送一个我是10号主机,我的Mac地址是多少,你可以给我通信了。此时我们就完成了一个Mac地址交换的问题。
路由器D是如何知道主机B的ip地址呢?
1.入口路由器D,收到的报文是包含了目标ip的。而且你要去的目标主机一定是在这个目标网络中的,主机肯定在。所以我就已经拿到了目标网络内目标主机的ip地址。
2.即使路由器D不知道主机B的ip地址也可以,局域网就规定了网络情况不是特别大,基本上一个局域网内最多几百台,而且大家的网络号一定是一样的,主机号不一样。比如说我这个局域网内有254台主机(8位主机号),我路由器直接通过某种方式,直接把局域网内所有主机遍历一次,相当于拿着你的ip地址,从1-254,遍历一下所有的主机,相当于给主机发报文,其中我就能知道所有主机的ip地址了。
ARP协议的作用
- 在网络通讯时,源主机的应用程序知道目的主机的IP地址和端口号,却不知道目的主机的硬件地址;
- 数据包首先是被网卡接收到再去处理上层协议的,如果接收到的数据包的硬件地址与本机不符,则直接丢弃;
- 因此在通讯前必须获得目的主机的硬件地址;
ARP协议的工作流程
对我们来说,现在的问题是知道你的ip,但是不知道你的Mac地址,所以我们可以在局域网内进行ARP。
这里就是一个先广播再单发的问题。
- 源主机发出ARP请求,询问“IP地址是192.168.0.1的主机的硬件地址是多少”, 并将这个请求广播到本地网段(以太网帧首部的硬件地址填FF:FF:FF:FF:FF:FF表示广播);
- 目的主机接收到广播的ARP请求,发现其中的IP地址与本机相符,则发送一个ARP应答数据包给源主机,将自己的硬件地址填写在应答包中;
- 每台主机都维护一个ARP缓存表,可以用arp -a命令查看。缓存表中的表项有过期时间(一般为20分钟),如果20分钟内没有再次使用某个表项,则该表项失效,下次还要发ARP请求来获得目的主机的硬件地址
ARP数据报的格式
在数据链路层,我们经常用的是mac帧协议,mac帧协议除了直接可以交付给网络层协议外,在Mac帧之上,有一个协议,我们称之为ARP。ARP协议只是在数据链路层的一个协议,它虽然在Mac帧协议的上层,但是它不属于网络层,只属于数据链路层。Mac帧收到数据帧之后可以把数据交给网络层对应的ip,也可以交给自己的ARP协议,它交给ARP协议取决于Mac帧对自己的有效载荷的判断(也就是当我们进行ARP请求的时候,交给ARP协议完成工作之后,ARP协议不会交付给网络层,而是再向下交还给Mac)。相当于这个ARP协议属于数据链路层底层自动完成的一个协议,叫做ARP。对我们来讲,只要我们在进行ARP请求的时候,这个数据帧一定根据它的帧类型交付给它的ARP协议,至此就完成了数据帧转发的功能,也不在向上交付。像这种不断向上交付的数据,我们更多的谈的是用户数据,这种类型ARP不向上交付的是管理数据,说白了就是这个ARP协议就是用来处理ARP请求的,本身就属于数据链路层,它不会向上交付。
![]()
红色框这部分是由ARP协议去形成的,换句话说ARP协议的整个数据报文是作为数据帧的有效载荷被数据帧封装了。所以Mac帧要封装ARP协议,ARP协议一定是在Mac帧上层。而且ARP协议里都是一些网络中的概念,没有有效载荷,因为ARP协议不需要向上交付。所以每一个大层里面还可以细分成各种各样的小层。
- ARP的请求大小是28字节,28字节不够数据帧的46字节(利用PAD字段进行填充)。
- 注意到源MAC地址、目的MAC地址在以太网首部和ARP请求中各出现一次,对于链路层为以太网的情况是多余的,但如果链路层是其它类型的网络则有可能是必要的。
- 硬件类型指链路层网络类型(例如以太网,令牌环网,无限WiFi,我们这里只谈以太网),1为以太网;
- 协议类型指要转换的地址类型,0x0800为IP地址;
- 硬件地址长度对于以太网地址为6字节;
- 协议地址长度对于IP地址为4字节;
- 前面4个字段都是填好的,就不用在管了
- op字段为1表示ARP请求,op字段为2表示ARP应答
发送端以太网地址和发送端ip地址就是填充我的MAC地址和IP地址。目的以太网地址我不清楚,所以这个字段就填充成全F,意味着这个字段是未知的。目的IP地址我也知道。
如果是ARP请求的时候,只有目的以太网地址这个字段我们不清楚。
PS:
- ARP协议也要封装mac帧,也要走局域网通信原理,一定是向下交付的。
- ARP请求里要填ip地址,实际上这个ip字段是上层去填写的,因为是上层收到了一个ip报文,上层要发起数据,但是因为没有mac帧,所以上层只能先ARP,所有的协议虽然都在数据链路层,但是一定要有人主动发起,所以上层再发起ARP的时候,就可以把对应的ip地址作为参数传给ARP协议,这个时候就可以向下传。有时候各种层之间也需要彼此的数据交互。
ARP传输过程
我们的A就是一个入口路由器,收到了一个报文,它的报文中携带的只是目的ip是IPB。当主机A收到一个网络报文,发现它要去的是IPB,IPB通过自己内部的路由表,然后通过目的IP和子网掩码按位与得到目标网络,发现你要去的目标主机和我这个路由器是直接相连的,你已经到达了入口网络了,到达了入口路由器,现在我这个路由器就负责把这个数据内网转发到主机B(也就是局域网转发到),可是我这个路由器并不知道主机B的Mac地址,所以此时主机A就先发起一次ARP请求获得主机Bmac地址,当然这个路上也一定用属于同一局域网的其他主机。然后主机A就开始填写ARP请求,硬件类型就是1,协议类型就是0800,硬件地址长度就是6,协议地址长度就是4,op就是1,发送端以太网地址就是MACA,发送端的IP地址就是IPA,目的以太网地址就是全F,目的IP地址就是IPB(因为报文里面就是IPB)。填好以后这个ARP请求就要向下交付封装mac帧,就需要填写以太网的各种字段,以太网的目的地址就是全F(因为我们不知道,在数据链路层中封装的数据帧是全F就叫做广播),源以太网地址就叫做MACA,帧类型就是0806(代表ARP请求或者应答)。
所以此时就构成了一个完整的数据帧,就通过网络被广播到局域网中,所有的主机就全部都能收到了,包括主机B,大家发现这个目的Mac地址是全F(广播),所以所有的主机就进行处理mac帧:报头和有效载荷分离,提取出帧类型,发现是0806,然后所有主机都把这个报文解包之后交付给自己的ARP协议。
主机拿到ARP后先对比目的IP地址,是自己的就处理,不是自己的就可以在自己的ARP层把ARP请求全部丢弃,理论上确实是这样的,可是任何局域网中的主机,可能向别人发起ARP,也可能被别人发起ARP;如果被别人发起ARP,意味着此时的ARP一定是一个ARP请求,别人是请求我的;如果我向别人发起ARP,我极有可能得到的是一个ARP应答。所以你发起一个ARP请求不要认为就完了,你还要让别人把ARP应答给你,但是任何一台主机都有可能承担这两种角色。
eg:主机B收到了一个ARP,但是主机B必须得知道这个ARP是请求还是应答!因为如果是请求就得给别人构建ARP了,如果是应答我就要拿出来对方的mac地址,然后给对方发数据报文了。所以当我收到一个ARP请求,我一定是先看OP字段的,OP字段表明的就是这个ARP协议是请求还是应答。
所以主机B拿到ARP后看见这个OP字段为1,所以就立马意识到这个是ARP请求,然后再看目的ip地址,发现就是自己,然后就要进行ARP的应答了。至此就完成了ARP的请求过程。
接下来主机B就要开始构造应答了,ARP的硬件类型就是1,协议类型就是0800,硬件地址长度就是6,协议地址长度就是4,op就是2,发送端以太网地址就是MACB,发送端的IP地址就是IPB,目的以太网地址就是全MACA,目的IP地址就是IPA(ARP请求里就有A主机的mac地址和ip地址)。然后主机B在向下交付封装数据帧报头。以太网的目的地址就是MACA,源以太网地址就叫做MACB,帧类型就是0806(代表ARP请求或者应答)。接下来这个信息就被主机B发送到网络里,这次虽然不是广播但是所有的主机还是都能收到,只不过这次所有的主机收到数据帧,分析报头目的主机是MACA,除A外的所有主机就全部丢弃了(在数据帧层丢弃),这次的丢弃就是正常的局域网通信,数据帧不是自己的。所以主机A就收到了数据。主机A收到数据就解包,解包之后知道这个数据是MACB给我发过来的,然后根据帧类型0806,识别到是一个ARP,然后就把有效载荷交给主机A的ARP协议。在主机A在ARP层,同样先看OP字段,发现是2应答,接下来看的就是发送端以太网地址,此时主机A就获得了主机BMac地址,进而就可以进行封装IP报文,单向的把数据从A发到B
为什么收到ARP后要先看OP字段,而不是看目的IP字段?
主机拿到ARP后先对比目的IP地址,是自己的就处理,不是自己的就可以在自己的ARP层把ARP请求全部丢弃,理论上确实是这样的。
但是你不能确定这个目的ip是你想要的数据,你必须得先知道这个是ARP请求还是应答,你才能决定你接下来要关心哪个字段。
比如:ARP应答压根就不关心目的IP,因为接收方只要判断出ARP是应答,这个目的ip就是它自己,所以我们必须先得找到op,才能决定关心哪些字段。
主机A收到来自主机B的数据帧,为什么不直接从以太网首部这里提取主机B的mac地址呢?
理论上,从这里提也可以,但是你收到的主机B的数据帧,在数据链路层并不清楚这个数据帧和哪个ip对应,没有ip对应的话,也就没有实用价值,因为你封装的报文都是给ip服务的。ARP协议里既有mac地址又有ip地址,就是为了告诉你mac地址和ip地址的映射关系,所以当上层下来的时候我们就可以根据ip找到mac地址,然后封装我们对应的数据包。
这个路由器D可以在局域网中发起一个ARP,然后路由器D就可以拿到主机B的mac地址,所以数据包此时就跟据目的ip知道了我要去的目的mac地址,所以再封装mac地址就到了目标主机。
ARP的过程,不仅仅在我们对应的入口路由器和目标主机之间有,比如路由器A想到路由器B,路由器这个设备天然的就会自动发现主机,说人话就是在局域网内根据自己的目标网络不变,然后自己从1开始遍历主机号,相当于给没台主机直接发送ARP,遍历的时候就发现了局域网内所有的主机了。换句话说:就是路由器A在路上的时候就有可能找不到路由器B,此时就只知道路由器B的ip地址,此时就发送ARP。任何时刻在路上的时候都可能ARP。
主机A经过路径选择到达了入口路由器然后到达主机B,难道每一次向主机B发消息都要进行ARP请求吗?
第一次向主机B发消息,入口路由器需要发送ARP获取主机B的mac地址。那么第二次,第三次...每一次发送消息都需要发送ARP获取主机B的mac地址吗,答案是不需要。这个ARP在局域网其实是很快的,但是路由器D不是只给主机B发消息的,可能给局域网内的所有主机都要发消息,如果每次都要ARP就意味路由器太忙了,所以对路由器来讲ARP是一个特别低效的东西。
ARP缓存表
实际上系统当中,是会针对ARP的ip地址和mac地址做缓存的。
查看缓冲的命令arp -a
我们在正常通信的时候,只有第一次通信的时候需要发送ARP,就认识主机了。之后我们就可以直接查ARP缓存,然后就可以直接找到目标主机。
我可以将这个ip和mac地址永久保存起来吗?
不可以! 主机B现在是一个健康状态。如果路由器永久的把ARP的ip和mac地址映射的关系保存起来,先不谈ip地址变化的问题,就是IP地址不变,主机B有一天网卡坏了,那么此时就直接把主机B的网卡更换了,此时主机B的mac就变了。如果你的路由器写死了,永久保存了,那么这个主机B也就永远上不了网了(至少在这个局域网内)。所以这个缓冲一定要有时间限制,一般比如10~20分钟是有效的,时间到了,系统就自动清理掉。让主机B有再被发现的可能。所以这个ARP缓冲是以分钟为单位进行缓存,只要一直访问就可以一直给你映射,只要时间到了,就会自动把他清理掉,清理掉之后,下次请求时就会在进行ARP,就重新拿到了mac地址。
如果我今天想知道和我处于同一个局域网内所有主机的mac地址,怎么办呢?
比如这就是我的子网和子网掩码。
通过子网掩码,我们可以看出我们的主机数一共是10个比特位,也就是2^10=1024台机器,这是因为我们用的是云服务器。
博主学校的校园网的主机数更多,一共15个比特位,也就是2^15=32768台机器。
一般家里的局域网的子网掩码一般是255.255.255.0一般是200多台机器。
所以我自己的ip地址我知道,子网掩码我知道 ,那么我就知道了网络号了,主机号我虽然不知道,但是我就可以构造一批ip地址。
假设:我的ip地址是10.0.8.0 子网掩码是255.255.255.0,我要构建ip地址很简单
cnt=1; while [ $cnt -le 255 ];do echo "10.0.8.${cnt}"; let cnt++; done
此时我们就把局域网内所有的主机全部罗列出来了。有可能其中有的ip是无效的,实际上ARP触发的时候就是我给你发送报文的时候。我只要尝试给这个主机发消息,就一定要先做ARP,意味着你的ARP的信息一定是会被缓存起来的。所以我可以采用ping的方案(ping就是用来检查网络连通性的,检查连通性的本质就是通过给你发数据,你给我应答,只有你给我应答了,才证明你这个主机是连通的;我给你发报文,就必须知道你的mac地址,所以你就必须先ARP)。
换言之,我们已经构造出来所有的ip了,我就可以直接ping这些个ip
cnt=1; while [ $cnt -le 255 ];do echo 'ping -> 10.0.8.'${cnt};ping -c1 10.0.8.${cnt}; let cnt++;done
通过这样的方式,我把局域网内所有的主机都ping完,只要我ping成功,就会给我们对应的ARP,然后他的MAC地址就被我们缓存起来了。
因为这样太慢了,所以我们写个脚本
增加执行权限
执行完毕后,再次查看ARP
我们此时就缓存了一大批的ip与mac地址,一共264条(最开始博主的机器只认识10多条,现在就认识200多个了)。
RARP
数据链路层上面有个协议是ARP,当然还有一个RARP,叫做逆地址解析协议。说变了ARP就是把ip转Mac,rarp就是把mac转ip。
其他重要协议或技术
DNS(Domain Name System)
DNS是一整套从域名映射到IP的系统
DNS就是一个域名。当我们实际在访问某一个网址的时候,实际上并不是在真的访问这个网址,而是你的浏览器首先自动的帮我们进行域名解析,拿到ip地址,ip地址拿到后,此时就拿到了服务器端的ip地址以及你要请求的服务端口,进而再去进行网络请求和访问。
PS:DNS则是典型的应用层的协议
DNS背景
- 如果一个新计算机要接入网络, 或者某个计算机IP变更, 都需要到信息中心申请变更hosts文件.
- 其他计算机也需要定期下载更新新版本的hosts文件才能正确上网.
- 一个组织的系统管理机构, 维护系统内的每个主机的IP和主机名的对应关系.
- 如果新计算机接入网络, 将这个信息注册到数据库中;
- 用户输入域名的时候, 会自动查询DNS服务器, 由DNS服务器检索数据库, 得到对应的IP地址.
至今, 我们的计算机上仍然保留了hosts文件. 在域名解析的过程中仍然会优先查找hosts文件的内容.这个文件除了主机会使用外,其他情况我们就都不使用了。
cat /etc/hosts
例如你想访问你主机,除了ping 127.0.0.1 也可以ping以下名称。
域名简介
www.baidu.com
- com: 一级域名. 表示这是一个企业域名(商业公司,表示它是以盈利为目的的). 同级的还有 "net"(网络提供商), "org"(非盈利组织) 等.
- baidu: 二级域名, 公司名.
- www: 只是一种习惯用法. 之前人们在使用域名时, 往往命名成类似于ftp.xxx.xxx/www.xxx.xxx这样的格式, 来表示主机支持的协议.
ICMP协议
网络层中我们都知道有协议叫做ip,实际上还有一种协议是在网络层内,但属于ip上面的,比如说ICMP和IGMP。
实际上有些管理员命令,用的是原始套接字,他们就能绕过传输层直接去访问网络层的内容,相当于直接可以向对端发送ip报文,而且不携带用户数据。
ICMP功能
- 确认IP包是否成功到达目标地址.
- 通知在发送过程中IP包被丢弃的原因.
- ICMP也是基于IP协议工作的. 但是它并不是传输层的功能, 因此人们仍然把它归结为网络层协议;
- ICMP只能搭配IPv4使用. 如果是IPv6的情况下, 需要是用ICMPv6;
比如你买好云服务器了,你要检测你自己的主机和云服务器是否连通,ip协议不提供可靠性,丢了就是真的丢了,有人说我写个socket用tcp,但是现在写个socket也没太大意义,因为你现在是要访问它,所以我们完全不用UDP和TCP,你只要向他发起一个ip报文就可以了,但是因为ip报文丢了不和你说,要不然怎么会有TCP的超时重传呢?所以我们只是用ip向对方发送报文的话,如果报文丢了,ip协议是不能通知发送方说你把报文丢了及其原因所以我们就设置了一种ICMP协议。
ICMP的最大的特点就是如果你把数据包发送了,到了对端主机,对端主机关机了,这个报文就丢失了,当然会经过多次尝试发送,发送最后失败的时候,就会由最后路由器反向的向发送报文的主机报告发送的情况。以前这个东西时不敢想的,因为我们的ip是不提供这个功能的,但是因为有ICMP,ICMP使用IP就能做到这样的工作。说白了就是ping命令底层用的就是ICMP协议,说白了就是向对方发送ip报文,对方收到ip报文后根据ICMP协议进行应答。
eg:当你ping的时候会看到一些icmp的序号,ip报文的TTL(生存周期),time就是来回时间。因为有ICMP这样的协议,我们才能看到这些东西。icmp_seq:序列号,表示第几个个响应包(递增的数字)。
ICMP一旦将报文发出,路由器收到,发送数据没发成功,ICMP就响应回去,路由器响应的原因就是协议规定,因为路由器和主机都得遵守协议。最后我们就能得到应答,应答报文中是会包含我们不同的错误编码,通过错误编码我们就知道它对应的是哪些种类的错误。
ICMP的报文格式
ICMP大概分为两类报文:
- 一类是通知出错原因
- 一类是用于诊断查询
ping命令
linux下ping百度
windows下ping百度
- 注意, 此处 ping 的是域名, 而不是url! 一个域名可以通过DNS解析成IP地址.
- ping命令不光能验证网络的连通性, 同时也会统计响应时间和TTL(IP包中的Time To Live, 生存周期).
- ping命令会先发送一个 ICMP Echo Request给对端;
- 对端接收到之后, 会返回一个ICMP Echo Reply;
一个值得注意的坑
有些面试官可能会问: telnet是23端口, ssh是22端口, 那么ping是什么端口?
traceroute命令

原理也很简单:我向你发报文,第一次的时候将生命周期设置成1发送出去,经过一个路由器转发,错了你就给我应答,应答之后,我就知道是哪个路由器了;然后第二次我把我的生命周期改成2,依次类推,所以我把我的报文的生存周期不断增多,这个报文传输的时间越来越远,每一个出错,丢弃之后都会给我应答,直到到达了目标主机,这样我就能把整个路径中的所有ip都打印出来。当然,这个其实是会变化,中短期内路由表的构成是比较稳定的,路由选择也是比较稳定的,所以路径一般是确定的,但是这个肯定是变化的, 早上执行和晚上执行都是会发生变化的。
NAT技术
NAT技术背景
- NAT能够将私有IP对外通信时转为全局IP. 也就是就是一种将私有IP和全局IP相互转化的技术方法:
- 很多学校, 家庭, 公司内部采用每个终端设置私有IP, 而在路由器或必要的服务器上设置全局IP;
- 全局IP要求唯一, 但是私有IP不需要; 在不同的局域网中出现相同的私有IP是完全不影响的
NAT IP转换过程
- NAT路由器将源地址从10.0.0.10替换成全局的IP 202.244.174.37;
- NAT路由器收到外部的数据时, 又会把目标IP从202.244.174.37替换回10.0.0.10;
- 在NAT路由器内部, 有一张自动生成的, 用于地址转换的表;
- 当 10.0.0.10 第一次向 163.221.120.9 发送数据时就会生成表中的映射关系;
实际上数据在经过NAT路由器出去的时候,不仅仅是把你的源ip替换掉,而是路由器会维护一张映射表。我们之前标识一对请求连接用的是源ip,源端口,目的ip和目的端口,这一组信息在自己的内网当中一定是具有唯一性的。说白了就是路由器在做转化的时候,除了把源ip替换过去之外,还要给我建立映射关系。实际上在做NAT的时候,端口号也有可能变化。
转化实例
NAPT
因为双方都具有唯一性,所以路由表会把这一对具有唯一性的值建立映射关系。所以报文在出去的时候,我们的路由表中就会维护这次请求建立的映射关系,因为彼此都有唯一性,所以可以做到互为键值,而且这些键值本身就有通信细节,所以当一个报文回来时,我们再把该报文的目的ip和目的端口,在替换成转化表当中,曾经的ip和端口,这样的话,路由器就可以把报文定向的交给客户端了。

所以对我们来讲,我们无数次出去的时候,就可能在路上建立各种各样的NAT映射关系,回来的时候就是不断的查这些NAT转化表的过程,其中这些表结构的维护,数据的维护量一定很大,所以路上的路由器一定是运营商的路由器,要求功率比较大,家用路由器就只需要维护你家里的那几台设备的路由器就可以了。
转化实例
NAT为什么能延缓ip地址不足呢?
因为有NAT的存在,所有的家用路由器都可以维护NAT映射关系,当你在进行外网请求的时候,NAT路由器帮你建立映射关系,帮你请求,请求之后把结果给你,然后在反查NAT表,交互给用户。所以,我们就可以做到,经过家用路由器给我们构建出来的一个虚拟的子网,就可以让所有的局域网内的ip地址都是一样的。以前入网的主机都需要公网,现在不需要了,直接用私网ip,中间路由器就可以帮我们做到映射,换句话说这些公网ip就只可以在公网中使用,一般是都是企业,运营商去用,包括你自己的云服务器,你扮演的就是企业的角色,你就有公网ip,除此之外就都是私网ip。
如果客户端A从来没有访问过服务器,服务器能否访问客户端A吗?
不行。因为客户端是个私有ip,所以服务器想反向的访问是不可能的,所以服务器最多能访问家用路由器,但是家用路由器这个NAT没有映射表,因为A从来没访问过服务器,映射关系不存在,服务器就访问不了。这样的话也变向的保护了内网的主机。所以你自己的机器别人想通过外网访问你是比较困难的。客户端A能出去,就是因为服务器的ip地址是全网内唯一的,所以你才可以访问。
浅谈虚拟机的网络连接模式
一些虚拟机在特定的场合下就会告诉你,网络的连接模式,有一种是桥接模式,有一种是NAT。
你的计算机是windows的,你在内部又装了虚拟机,就相当于在你的计算机里又跑了一个计算机,但是网卡只有一个,现在虚拟机要上网就有两种方式:
一、NAT模式
我的虚拟机把你的windows这台机器当成一个大的路由器,这个大路由器给我的虚拟机构建一个子网,我虚拟机的所有请求都通过你的windows机器向外网发起请求。
说人话:把windows当成路由器就需要windows帮助虚拟机维护NAT转化表,所有所有的报文在其他人看来,好像都是你这个windows机器在发起请求。这就叫做NAT。
这种模式就是让虚拟系统借助NAT(网络地址转换)功能,通过宿主机器所在的网络来访问公网。也就是说,使用NAT模式能够实现在虚拟的系统里面直接访问互联网。NAT模式下的虚拟系统的TCP/IP配置信息是由VMnet8(NAT)虚拟网络的DHCPserver提供的,无法进行手工改动,因此虚拟系统也就无法和本局域网中的其它真实主机进行通讯。采用NAT模式最大的优势是虚拟系统接入互联网很容易。仅仅需要宿主机器能访问互联网,不需配置IP地址,子网掩码,网关。可是DNS地址还是要依据实际情况配的。
二、桥接模式
让windows直接联网,让虚拟机也直接联网,就相当于我们两个共用网卡,但是我们两个的地位是对等的,也就是虚拟机就是局域网中的某台主机,这就是桥接。
在桥接模式下,虚拟机虚拟出来的操作系统就像是局域网中一台独立的主机,它能够访问网内任何一台机器。
在桥接模式下,必须手动为虚拟系统配置IP地址、子网掩码,并且还要和宿主机器处于同一网段,这样虚拟系统才能和主机进行通信。
配置好网关和DNS的地址后。才能实现通过局域网的网关或路由器访问互联网。
桥接模式:虚机和物理主机可通信,可与外网通信。
NAT说白了就是维护一个内网到外网,外网到内网的一个关系,他俩互为键值,所以就可以直接出去进来,进来出去。
NAT技术的缺陷
- 无法从NAT外部向内部服务器建立连接;
- 装换表的生成和销毁都需要额外开销,都需要花内存;
- 通信过程中一旦NAT设备异常, 即使存在热备, 所有的TCP连接也都会断开;
NAT和代理服务器
代理服务器
正向代理

为什么要有个代理服务器呢?
反向代理

当用户访问时候,访问的不仅仅是服务器,而是也有个代理服务器,将来所有的请求都是先请求代理服务器,但是我这个代理服务器不给你做任何的业务处理,仅仅做业务转发,根据后端每一台机器的负载情况进行业务转发。
我们如果把所有的请求都打在一台机器上肯定是不行的,因为就会造成旱的旱死涝的涝死,而且用户体验也是极差的。最理想的情况就是较为均衡的将请求打散到每一台服务器上,这种通过代理服务器做到的策略就是负载均衡。
服务器收到请求后,要么就可以把响应发给代理服务器,通过代理服务器发给客户端;也可以直接响应回客户端,不经过代理服务器。端口我们是有in端口和out端口,像这种方式,我们就可以把服务器的out端口打开,in端口关闭,也就是客户端不能直接像服务器发消息,但是服务器可以向客户端发消息。这样的话,代理服务器,主要用来做公司内部的入网许可,请求连接的有效甄别,还有负载均衡。
那么NAT和代理服务器的区别有哪些呢?
- 从应用上讲, NAT设备是网络基础设备之一, 解决的是IP不足的问题. 代理服务器则是更贴近具体应用, 比如通过代理服务器进行翻墙, 另外像迅游这样的加速器, 也是使用代理服务器.
- 从底层实现上讲, NAT是工作在网络层, 直接对IP地址进行替换. 代理服务器往往工作在应用层.
- 从使用范围上讲, NAT一般在局域网的出口部署, 代理服务器可以在局域网做, 也可以在广域网做, 也可以跨网.
翻墙的原理
我们访问不了外网的原因就是因为有墙。
背景
当你的机器发起请求一定是经过网络,运营商一定是最先收到你的请求的,因为你必须走它,基础设施就是运营商搭建的,而且你的网费流量费都是交给人家的。然后运营商将你的请求转发给服务器(比如说QQ),QQ在反向的给运营商做相关的转发把数据交给你。所有的请求都要经过运营商,运营商在这个环节里起的就是一个霸主的地位。如果你的报文没有经过任何加密的话,你所有的报文都是裸的,实际上报文在转发的时候就是在选择子网的过程,子网是提前建设好的,所有的报文在任何一个环节当中,一定是在某个时刻处于一个网段的也就是一个局域网,也就是一定处于局域网通信的过程中,所以我就可以在报文发送的路上以中间人的方式进行抓取报文(如果报文没加密)。换句话说你请求的是QQ,运营商是能得知的。
我们一般访问服务器的时候用的是HTTPS协议,你也一定是要有url的,比如你访问某个网站,你通过url向对方发起请求,就给他发送http报文,一定包含了你想要请求的目标网址。对我们来讲,运营商是可以得知你请求的很多信息的,运营商内部具有一定的白名单策略,只要你访问的是国内的一些公司就正常给你转发,但是比如你访问谷歌,我们就直接被拦截了。
在我们看来是完成了域名解析的,然后就向这个ip发起请求,ip地址是划分区域的,如果你访问了这样的ip的话,运营商就识别到这个ip是国外的ip,是处在黑名单中的一个ip,就不让你建立连接。即便是你建立了连接,后面你再去访问谷歌的相关资源也访问不到,运营商可能在内部对你的内容做处理。
原理
我们想要去外网就得做这两件事情:
- 1.我们如何做能骗过运营商呢,告诉运营商你访问的是一个合法的网站。
- 2.将来你骗过他以后,你怎么回来呢,你回来的时候也是需要骗过运营商再把信息转给你。
首先你得具有一台可以访问外网的机器,这台机器:
- 1.是能被我的内网所访问的
- 2.可以去访问对应的外网。
这样的机器是存在的,有一些云服务器就是这样的。比如:我要访问香港的机器,香港是国内的运营商照样需要把报文做转发,香港是可以访问国外的,所以香港的机器就可以做这样的事情
第二步,我在这台机器内部部署代理服务,最常见的代理服务比如说Nginx.
什么是Nginx
Nginx (engine x) 是一个高性能的HTTP和反向代理web服务器,
Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,在BSD-like 协议下发行。其特点是占有内存少,并发能力强,事实上nginx的并发能力确实在同类型的网页服务器中表现较好,中国大陆使用nginx网站用户有:百度、京东、新浪、网易、腾讯、淘宝等。
你想要进行上外网的时候,你自己一定要安装一种客户端,这种客户端的作用和Fiddler一样。以前你的浏览器是直接访问运营商然后访问公网的,现在你的这个客户端软件就相当于把你的浏览器劫持了,然后你的所有请求就由这个软件做处理,然后这个软件带你去请求。
比如你今天访问谷歌,这个请求不是直接从你的机器发送到运营商,而是先被你这个客户端获取到,然后把你访问谷歌的这个请求当做正文,形成一个新的访问代理服务器的请求。所以此时就把你的请求交给运营商,运营商发现你此时访问的是这个代理服务器,没有问题。当然,运营商也是会考虑这样的问题的,运营商会对你文本中的内容做相关的分析,分析你信息中有没有访问外网的信息,比如扫描出来你的正文部分还是包含了谷歌,运营商照样给你丢弃这个请求。所以你的客户端不仅仅是把你的请求包裹到一个新的请求中,而且还要进行加密(最主要的目的就是不让运营商知道我是谁)。所以此时运营商就交给了代理服务器,此时代理服务器就把访问我的请求直接去掉,拿出内部真正的东西进行解密,解密之后就得到了访问谷歌的请求,此时你的代理服务器就可以直接访问谷歌,谷歌就把响应返回代理服务器,然后代理服务器就把谷歌的响应作为一个报文加密封装起来重新形成一个新的响应,此时在返回给运营商。运营商检测不出来就返回给你的客户端,客户端收到后就去掉报头,把正文解密出来,然后把正文的http交给你的浏览器,剩下的就是你的浏览器对谷歌的http做报头处理,正文渲染,然后你就拿到了对应的网页。
所以,如果你自己要上网,你要有一台能够访问外网的服务器,然后编写一个客户端,他俩都要有加密和解密的功能。
我们一般在云服务器上是没有办法绑定自己的公网ip的,为什么呢?
博主的云服务器是有一个公网ip和内网ip的,这是通过腾讯云的后台查看的
单单在博主的机器上只能查到内网ip
实际上,你自己的请求是经过反向代理服务器,反向代理再转发给服务器,所以你有时候看到给你分配的公网ip完全不是你这台机器的ip,这个公网ip有可能就是干脆模拟出来的。
当你请求的时候请求的是代理服务器,代理服务器就会把你的请求转发到你的服务器上,所以你自己在你的机器上查的时候只能查到你的私有ip,你在云服务器厂商那里你可以看到公网ip是啥和私网ip是啥。
实际上所有访问公网的这个请求最终相当于内部建立了一张映射表,将来所有人想访问特定区域的ip地址都会发到代理服务器上,内部做映射帮你找到你的机器,所以通过反向代理找到你的机器最后让你使用你的机器,所以你所看到的公网ip并不是真正的ip,这是腾讯给你模拟出来的ip,所以你的机器里并不存在这样的公网ip地址,你也就没办法绑定,所以这样就是为什么在线上生产环境当中,我们必须得保证不要绑定公网ip,因为这个公网ip本身就不存在,此时建议绑定0,这样就相当于从任何地方来的,在主机上任何的报文情况我都能收到,线上生产环境全部建议用0。
为什么socket通信时服务端不能绑定云服务器的公网ip及为什么要绑定INADDR_ANY?
当然你在socket通信的时候是可以绑定你的云服务器的私网ip的,如果是在同一局域网,客户端就可以通过访问你云服务器的私网ip进行通信(就是局域网通信);但是我们是在不同的局域网,客户端光访问你的私网ip是无法进行通信的,所以客户端就必须知道你的公网ip。但是你的云服务器实际上并没有公网ip,这个公网ip是腾讯给你这台云服务器模拟出来的并且腾讯将这个公网ip和云服务器自己的私网ip做了映射,只要访问这个公网ip,最终就是访问到你的云服务器上了。
可是对于云服务器来讲,我们绑定的时候也不能绑定这个公网ip,因为拥有这个公网ip的很可能是一个入口路由器,你写的全部服务都在你的云服务器上,而拥有这个公网ip的路由器并不提供服务,所以我们就不能绑定这个公网ip,你可以绑定的就是你的服务器的私网ip,这样的话只要客户端访问这个公网ip,就能直接映射到你的云服务器上,使用云服务器上缩写的服务。
但是我们一般也不进行绑定云服务器的私网ip,我们一般绑定的都是INADDR_ANY。
INADDR_ANY
转换过来就是0.0.0.0,泛指本机的意思,也就是表示本机的所有IP,因为有些机子不止一块网卡,多网卡的情况下,这个就表示所有网卡ip地址的意思。
比如一台电脑有3块网卡,分别连接三个网络,那么这台电脑就有3个ip地址了,如果某个应用程序需要监听某个端口,那他要监听哪个网卡地址的端口呢?
如果绑定某个具体的ip地址,你只能监听你所设置的ip地址所在的网卡的端口,其它两块网卡无法监听端口,如果我需要三个网卡都监听,那就需要绑定3个ip,也就等于需要管理3个套接字进行数据交换,这样岂不是很繁琐?
所以出现INADDR_ANY,你只需绑定INADDR_ANY,管理一个套接字就行,不管数据是从哪个网卡过来的,只要是绑定的端口号过来的数据,都可以接收到。