目录
1.网络发展
2.认识 "协议" 和 标准
3.网络协议初识
4.OSI七层模型
5.TCP/IP
6.网络传输基本流程
首先,说到网络你的第一印象是什么?
站在普通人角度肯定就是我可以通过网络做各种事情,刷抖音看B站打王者还有今天在这里你看到的CSDN的文章。但是今天我们要理解的网络,是要站在一个技术人员的角度去理解网络!
1.网络发展
网络不是凭空而来的,是先有了计算机---1946年第一台ENIAC后才有的网络。然后随着芯片的发展,计算机变得越来越小和高效化,又因为本身的性能很不错,所以后续广泛被实验室采用。
- 独立模式:开始在实验室的时候要进行数据的处理。假设有A、B、C三个人各自有不同的工作要做。A需要把数据做统计;B需要把数据做成表格;C呢要把数据做可视化的处理。三个人要互相之间协作,这之中虽然有计算机来帮我们,但A处理完数据要把数据拷贝到光盘类的存储设备再交给B处理,这之间要有人的参与才行,所以效率很低。
- 网络互联:有了需要,那当然就有人满足。后来就有人把计算机和计算机连接起来,可以将人参与的部分交给机器。
- 局域网:后来实验室和实验室都有局域网LAN,需要合作,实验室之间需要进行网络通信,所以局域网和局域网之间就可以通过路由器进行通信了。
- 广域网:要上网必须存在两个设备,调制解调器,路由器。如果把外网比作大的局域网,家里的比作小的局域网,那么就需要通过路由器连接外网,没有路由器你也就无法上网。随着网络的扩展,不断的变大变大,城市和城市间也就有了局域网,也就有了WAN广域网。全世界的网络就可以通过设备进行上网了。广域和局域只是学术上的差别,只是规模的差别。
2.认识 "协议" 和 标准
什么叫做协议?
生活当中肯定会有协议,也就是约定。
主机A想给主机B发送数据,数据也是有类别的,有些数据就是单纯的数据,有些数据它是具有特殊含义的。有的是想让目标主机将数据删除,或者让目标主机进行重传。
所以数据是由类别的,就比如文件,文件是有属性+内容的,无论是内容还是属性,在计算机中都是01序列,但是在我们认知的时候,数据是有类别的,有些是属性,有些是内容,因为类别的不同,我们处理方式也应该不同。
我们为了能够快速的让两个相隔千里之外的计算机,能够区分出数据是哪些类别,每一种特定的类别当中的某一些数据,比如给你发送1234的时候代表什么含义,所以我们就需要用提前约定好的方式,来减少双方通信的成本问题。
举个栗子:
以前没有手机的时候,但是总有一两个张三同学,家里有钱配了电话。然后我们班同学,就可以找张三打电话。那时候打电话有一个特点,我给你打电话,如果你不接,那肯定是不收费的,如果你接了,那打电话的人花钱。如果我给你打电话,对方不接就不扣电话费。
那我李四出发前,跟父母约定,给家里的座机打电话,如果响一声,说明我在报平安;如果响了两声,代表我没钱了,赶紧给我打生活费;响了三声,说明 我有其他事情,这时候你就接电话,我会用我朋友的电话,它的电话号码就是123456,那么爸你也记下来。
然后有一天,你打电话,然后响了一声,尽管没有通话,但是提前约定过,你爸也就知道了你这家伙在报平安。后来快放假了,你打电话,响了三声,你把把电话接起来,这时候你俩就可以正常通话了。
那么你在离开家之前,跟你爸做的沟通,响一声响两声响三声代表什么含义,这就叫做约定,而这就叫做你和你爸达成的协议。为什么要这么做?因为他可以减少成本。如果没有跟你爸做过约定,你打电话响了一声,然后挂掉,你爸就不认识,也就不能做出有效的动作。这样的话,你这一次报平安的效率就非常低。那如果我们提前约定好,我们直接发送一个很短的数据,对方立马就能意识到,我们就可以以最短的方式让对方做出对应的行为。所以协议,本质是为了双方通信更高效。
计算机是两台机器进行通信,机器呢,也是需要通过软件,用计算机语言来表达两台计算机之间的协议的。比如两个计算机,设定一种计算机之间的协议,A计算机呢它和B计算机上部署了同一个程序员所写的代码,然后程序员定期从B主机向A主机发送一个字节的数据叫做1,接收看到这个1就立即意识到发送主机呢是健康的。相当与a和b就做了约定。A读到1就说明我这个机器是正常运行着的呢。读不到了说明我这个机器已经崩溃了。这就叫做两台机器之间的约定。也可以称作是一种协议。协议规定数据字节就是一个字节,数据内容就是1,这就是约定。
那么两台主机定好协议就可以了吗?
举个例子:
美国的同学跟西藏的同学定好了协议,在通话中说1就是吃饭,2就是休息。两个人也都遵守了协议说1,但是美国的同学说的话内蒙的同学听不懂,双方协议虽然是一样的,但是语言不一样,所以就无法完成正常的协议。这是什么意思呢?
计算机中01代表就是不同的数据,可能有的硬件设备用频率的密和疏来表示01,如果不同的计算机厂商表示01的硬件不一样,虽然规定发hello是什么意思,但是这些不同厂商的硬件二进制表现方式不一样,即便大家同样遵守协议,但对不起,我们上方依旧无法识别对方什么意思。
光光有协议还没用,必须要让这些计算机硬件厂商要以同样的规范来处理01问题。这个时候就必须要有人出来规定我们的硬件通信标准,不光是软件,在硬件上我们也要做标准。比如华为的5G高通的4G诺基亚的3G,这些全部都是约定。当协议一旦确定好,那么这个协议就称成为了行业标准。当有了行业标准之后,所有的厂商都得遵守。为了各品牌的主机能够通信,我们既要有硬件标准也要有软件协议,二者缺一不可。
只要网络存在,那么一定是硬件上有标准,软件上有协议的这样的一个集合体。才能够正常进行推进。
3.网络协议初识
首先我们要有一个概念: 协议是软件,软件是可以分层的。
1. 操作系统要进行协议管理,先描述,在组织。
所以之后的协议落实在代码中,它都是要定义成各式各样的结构体或类,那么协议就可以以结构体对象的方式发送给对方,这个就称之为报头
2. 协议本质就是软件,软件是可以"分层"的。
什么叫做分层呢?关于软件分层,在学C++的时候,可以写各种类,然后再main函数当中创建对象,使用类当中的方法,这就是一种软件分层。main函数里呢创建这个对象就是使用这个对象,那么在类内部呢就叫做方法的具体实现,所以就把方法的实现和使用就分为了两层软件层。
在Linux中,一切皆文件,为了维护文件看待方式的通用性,将所有的文件都看作我们的struct_file对象,内部包含函数指针,指向底层不同的方法。这,就叫做分层。
多态,有各种继承关系,有基类有派生类,派生类还可以再被继承,那么每一层继承体系就可以理解成是一种软件层,所以我们想给大家的第一个概念就是软件是可以被分层的。
3. 协议在设计的时候,就是被层状的划分的。
举个例子:
比如我在给你打电话,我们约定食堂门口吃饭,然后到食堂门口,当我们打电话的时候,我拿着我的电话,你拿着你的电话,是不是可以认为,我直接在和你通信呢?
站在应用层的角度,我是在和你直接通信。
但如果站在技术人员的角度,你这个人没有直接和对方沟通,而是你把你的话交给了手机,你的手机在跟对方的手机在通信,然后对方的手机做解码转化成语言在播放给对方。
所以这里有个非常重要的概念,我们平常在打电话的时候,其实就是一种分层的概念。我们有人的语言层,我们用中文在沟通,我认为我在和你直接沟通。然后再底层,是两部电话,它们通过它们所能识别的语言再进行沟通。所以我们人在打电话,它至少是两层协议或者说是两层通信的机制。如果有一天,两个老外打电话,相当与把语言层切了,由中文变成了英文,那么影不影响底层的电话协议呢?并不影响,双方正常可以使用电话通信。
我们的软件在设计是可以被划分成层状结构。这时候就有了一个问题。
为什么要划分成层状结构?
a 一般场景都比较复杂。比如我跟你面对面在沟通,我还要给你分个层,假设我们都有一个助手,我把我的话交给我的助手,我的助手再把它交给你的助手,你的助手在交给你,这不就是脱裤子放屁吗。只有我们俩太忙了,我才把要说的话交给我的秘书,我的秘书再交给你的秘书,等你不忙了你的秘书再把话交给你。这倒是可以。我们为什么要划分成层状结构呢?第一个是为了面对复杂场景,然后我们就可以通过层状结构来进行
b 功能解耦。所谓的功能解耦就是每一层解决不同的问题。比如我们打电话,我们沟通的是什么时候吃饭,打游戏,我们俩沟通的是业务上的事情。那么这两部电话沟通的是,我们通信频率是多少,用什么样的编码和解码方式,要不要加密,我们通信的时候要调的哪个频率用哪个基站来接收,它们关心的是这些问题。
大家可以发现,人和电话关注的共同点不一样,必须是人和电话共同来完成打电话这个工作,但是这个工作交给我们的人和电话时,不要把它两个的工作然在一起,就好比在两个人还得再沟通,我们通信的频率是多少这些问题。这就很奇怪,让同层的角色呢关注自己本层的功能。你关注你的我关注我的,我们通过接口的方式互相调用 ,这就是协议通过分层来进行的功能解耦 。解耦之后便于人们进行各种维护。
什么叫做各种维护呢?比如电话有bug,电话有bug不代表人有问题,只改电话就行了,如果把电话和人合起来,如果电话有问题,那就需要在这么大的软件体中去找问题。但如果分层了,就只要在电话里找就可以了。甚至问题多了搞不定了,可以把整个方案全部替换掉。替换成其他方案也是可以的。
分层呢有如此之多的好处,我们为了在网络通信时面对复杂场景时,为了能够进行更好的网络通信,我们就把网络协议也涉及成了层状结构。
然后我们再来谈一谈协议怎么定呢?如果今天,我们两个人面对面沟通,通信很容易。如果相隔五百米就很困难了,我就得扯着嗓子喊,有可能你还听不到。如果相隔五千米,那么它的通信场景就更复杂了。
我们呢,通信的复杂,本质是和距离成正相关的。换个问题,为什么会有网络问题呢?很简单,因为A和B两个主机通信的距离变长了。那么如果两个主机是长距离传输,你说它变复杂了,那么复杂体现在哪里?这不就是协议栈要解决的问题吗?复杂的问题有哪些,然后把它拎出来,再去思考为什么会有这么多层就可以对应上了。
应用范畴
0.如何处理数据 ---应用层
通信范畴:
1.如果我发出的东西对方没收到怎么办? 丢包----传输层问题
2.一个目标主机跟你距离千里之外,和你距离千里的主机可不止这一台,有成千上万台,你这一台机器,怎么从这千万机器中找到目标主机呢? 定位问题 -----网络层
3.我现在要把数据从A主机跨网络送到B主机,可是A主机跟B主机相隔几千公里上万公里,这么长距离,可不是拉根网线就过去了,而是你的A主机不是把数据直接交给B主机,而是交给中间的路由器,由路由器交给下一跳路由器,直到交给B主机。所以你要保证你的数据从A主机交到下一个主机或者设备。假设有十个设备,你是不是得先保证A主机把数据交到1路由器,然后由1路由器再交给2路由器以此类推,所以还要解决 解决下一跳主机的问题, -----数据链路层
4.解决了丢包、定位、下一跳主机的问题最后这个数据才能被对方收到。 ------物理层
这个层次的划分呢,对应的就是五层协议,而使用时我们是软件,而只关注上四层,物理层我们不关注,我们把这样的分层的方式呢,在现在的应用场景当中称为基于TCP/IP协议定制好的层状协议
操作系统,有一个非常关键的概念,就是计算机的层状体系结构。
第一层硬件,第二层驱动,第三层操作系统,在这之间还有 system call(系统调用),第四层用户层(lib,shell,应用软件)。
那物理层对应的就是曾经的硬件,
数据链路层对应的就是该硬件匹配的驱动程序,今天谈网络,这个硬件就是网卡驱动。
把传输层和网络层是在操作系统内部实现的,也就是传输和网络层属于操作系统。
然后应用层就是根据系统调用接口设计的上层的应用。
换句话说,我们将来的协议既包含上层应用如何写,又包括操作系统怎么做,这就叫做网络协议。虽然一行代码都没写,但未来实现网络通信时,实现的是传输层给我们向上提供的系统调用,然后用系统调用我们就可以完成网络通信了。
这也就是为什么丢包(传输层)和定位问题(网络层)把它定义到通信范畴。
这就是网络协议栈和操作系统对应的关系了。所以,未来学习网络的时候,应用层代码用的依旧是系统调用,所以,你未来写的网络编程,本质依旧是系统编程,因为你用的依旧是操作系统。其二,我们在学习网络原理的时候,传输网络和数据链路层它既有操作系统的内容,又有驱动的内容但最本质的是我们依旧还是在学习操作系统。所以操作系统和网络的关系是操作系统包含网络。
那我们的传输层当中一个最重要的协议叫做TCP,在网络层最重要的协议叫做IP,为什么要叫TCP/IP协议呢?因为传输层和网络层协议在操作系统内实现,是两个最重要的通信范畴的核心协议。我们整个协议就以他来命名了·。
4.OSI七层模型
可事实上,在网络协议最初定义的时候不是按照我们讲的这种方案来订的,它是按照自己的方案订出来的,我们把它称为OSI七层模型,包括物理层,数据链路层,网络层,传输层,会话、表示、应用层七层。下四层完全一样,上面三层被压缩成一层应用层,首先先有OSI的七层模型,后有TCP/IP五层,
它们的关系就像蓝图跟具体实现的关系,就跟草稿和具体叫作业的关系 。那么这个标准定义出来了,这个定标准的人不一定要写代码实现。比如我定一个标准,不一定是我要实现的。而是由其他顶级的研发团队去做的,这些研发团队发现下四层挺好的,但是发现无法将上三层在应用层上拆开,所以OSI规定是七层,实际落地的时候就变成了我们现在所看到的TCP/IP五层协议。
其实OSI设计的非常合理,虽然在实际中并没有严格按照OSI标准,但是下四层是严格按照OSI的,只有上三层没有做成三层,而是做成一层,而是因为应用层比较复杂。虽然在标准协议中没有实现它,但是在所有的网络程序写出来,把应用业务带上,你都可以找到这三层。虽然OSI这前三层定出来了,但是实际实现的时候发现这个无法在操作系统内部进行实现,只能把它交给用户了,交给用户处理,这就是TCP/IP跟OSI的关系。
最重要的内容是七层模型,我们也都知道,每一层呢他都要解决不同的功能,他在解决它的这些功能当中比较关键的点呢就是我们这OSI七层模型呢,必须得清除的意识到每一层它都有它自己的功能。应用层也要解决数据收到之后我们该如何处理的问题。
我们把这种基于传输层TCP网络层IP构建的一整套生态叫做TCP/IP协议,当然我们的主机是要经过长距离传输的,他会诞生新的问题,我们有配套的方案。可以看到这个方案是一个综合性的方案,会解决各种各样的问题,所以呢,一个问题一复杂,你把他揉在一起,你想解决当然可以解决,但是带来的维护成本就会非常大,所以我们一定会把复杂问题做分解,然后把相关的问题放在一起,统一去解决。那么这样就能慢慢的在软件分层上在软件设计上以层的方式解决每一层相关的问题,然后层和层之间相互协作就能完成我们解决一个系统问题的这样的一个整体的目标。
OSi是一种框架性的涉及方法,帮助不同的主机完成数据传输,它有一个特点,将服务、接口和协议明确区分开来了。这个没有问题,你后续在写网络通信代码时无论你怎么设计服务器,都绕不开别人设计的这三大概念,只不过很多教材和课件里说它既复杂也不实用,所以按TCP/IP四层协议来讲。它复杂但并非不实用,如果后面再使用的时候我们自己要设计一个应用层的服务器的话,其实你就直接或间接就必须得写会话表示这样的软件层。这东西就跟一些设计模式一样,虽然你一行代码都没写,但我知道你想把代码给写好你就是这个样子。
5.TCP/IP
TCP/IP协议呢我们统一把它叫做TCP/IP协调簇,采用了五层协议,一般每一层都会调用下层所提供的网络来完成自己的需求。
物理层:主要解决的是信息传递的电计特性,比如通信的时候我们采用的一些物理的介质,比如网线、双绞线、WiFi、光纤。连接的就是家里的猫,到了家里之后,你家里的猫在和路由器一连接,路由器主要的工作就是构建局域网,这个时候你就可以连接路由器就可以开始上网了。而路由器最终所有消息转发呢,就会经过你家里的猫,然后调制解调通过各种数字或者其他信号进行各种其他转化推送到网络当中。物理层主要解决了传输速率、传输距离、抗干扰性、集线器这样的问题。 再物理层工作的有两个设备,一个是集线器还要一个叫做调制解调器。集线器作用是信号在长距离传输可能会衰减,衰减了就不可能长距离传输,所以在数据被运营商拿到的时候他可能会给你你做信号放大的工作。
数据链路层:主要负责设备和设备之间数据帧的传送和识别,比如在传输之前如何进行帧同步、在转发的时候数据帧如果出错、传输的时候信息发生干扰、还可能进行的自动重发、还有数据校验这样的工作。常见的数据链路层呢,对应的协议最终就是我们传说中的局域网。他就会有各种各样的网络标准,常见的有以太网、令牌环网、无线滥等等,局域网标准是不一样的,这里是重点要画起来。就相当于我们要意识到,我们可能在家里,在学校,在公司,我们使用的这个局域网它可能是不一样的,他都有可能。局域网存在一个很重要的设备叫做交换机,交换机这个设备在局域网当中就可以划分很多很多的专业点叫做碰撞域。
网络层:解决的数据包长距离传输如何定位目标主机的问题,最主要的就是相当于做地址管理和路由选择。最主要的是根据目的IP地址来进行目标主机做定位。核心的设备就是路由器。基本上物理层数据链路层网络层这三层协议就可以充分构建出我们路上的相关设备,通信的时候是两台主机,A主机和B主机,这两台主机相隔千里,我们路上就有很多设备来帮你进行数据路由。所以运营商在物理层数据链路层网络层做基础设施就够了,但够了不代表它就会这么干。有这三层,我就能保证把数据从A主机送到B主机了。但是有这种能力不代表你1100%每次都成功,所以做不到的话怎么办,所以就需要有数据包在长距离传输时我们要有可靠性的部分,这部分就由传输层来做了。
传输层:传输层最典型的就是TCP协议,它将数据可靠的从A主机送到B主机。传输层有没有工作的设备呢?没有,也可以所有,指的就是发送数据的主机自己负责
应用层:我们把数据传送到对方之后,它呢就要结合我们对应的数据还有协议呢来完成我们一些特定的功能,我们就可以使用应用层进行数据分析得到我们应用层的一些逻辑。最典型的像HTTP,FTP这样的协议
6.网络传输基本流程
网络传输基本流程
网络整体结构是分层的,说白了就是软件结构上分层的那么每一层都有它的功能,分为应用层 传输层 网络层 数据链路层
每一层都有代表的协议
问个问题,如果有两台主机在同一个局域网,那么这两台主机能不能之间进行通信?答案是能。连接同一个路由器,就能投屏,说明我能给我的电视通信。结论,在同一个局域网两台主机能够直接进行通信。
我们的数据呢并不能直接从我们的应用层直接到对方的应用层。
从逻辑上讲,我们的应用层和对方的应用层在直接通信,在物理上讲,应用层是无法将数据直接发送给对方的。
就比如你和你的朋友一个住在1栋四楼一个住在2栋四楼,你想把礼物送给你的朋友,不是你直接送1栋的四楼直接就飞到2栋的四楼直接就把礼物送过去了。而是你应该先下楼,然后再到2栋楼下,再上楼才能把礼物送给你的朋友,而你的朋友不关心你怎么过来的而关心,我的一个好朋友给我送了一个礼物,这叫做再逻辑上你的朋友觉得你把礼物送了过来,而没有托人给你。
这就是逻辑上和物理上,而以后我们学习网络我们要尽量站在物理的角度,所以我们今天学习的网络它必须自顶向下将数据报文交付给最底层,在路上跑完之后,然后才能再自底向上被你主机收到之后,然后才能把数据交付到应用层,它必须在物理上是这么走的。以后站在工程师的视角我们要有这样的认识,但并不代表我们直接认为上层呢把数据直接交给我这种理解是错的,不过我们既可以站在用户角度也可以站在工程师角度理解这样是最好的。
重点呢是介绍一个概念:每一层都有自己的协议定制方案
那么其中每层协议都要有自己的协议报头。好我们人生中第一次出现了一个名词,协议报头。先把概念说了。当我们从上到下进行交付数据的时候要添加报头,从下到上递交数据的时候,要去掉报头。
这个就是第二个要给大家建立的一个常见的概念。我们先来理解这个概念怎么理解,再去理解局域网两台主机为什么可以直接进行通信。
这里呢主要是两个问题,
第一个:协议报头是什么?
第二个:为什么要添加报头?
网络我们虽然一直在用但是我们也感受不到,但是作为我们来讲,网络我们虽然没有感受到但是类似的常见我们倒是见到了不少,最典型的就是网购,网购的时候比如说我在拼多多二手的手机,那么这个二手的手机我花了500块买的,买方要给我们的手机打个包,说白了就是要把手机拿个手机盒装起来,难道卖方就是把你的手机装起来就直接拿给顺丰发了吗?并不是,现实生活中并不是只是一个盒子,而是还要填写快递单,这个盒子没什么用就认为盒子和手机是一样的在一起的。这个单子不是给你看到而是要给顺丰看的,而你要的不是这个单子而是手机。那我们收到的快递单就称为我们收到的快递的报头信息,我们收到之后要对报头进行解包,那么曾经就一定有人给我做过封装,那么我解包把里面的东西拿出来,这个就叫做交付的过程,只不过这个解包和交付的过程就是我们自己做的,因为只有两层吗。所以我们下面正式回答之前的问题。
第一个问题:什么叫做协议报头?当上层把数据交给下层的时候,下层也是有对应的协议的,下层要做的就是把上层给我的数据结合我这一层的对应的报头给他多添加一部分报头数据,以供未来对方的同层协议解包和对数据做提取,那么这个呢就叫做协议报头。
说白了就是同层协议收到了一个数据之后,我们在数据之外多出来的这一部分我们就叫做报头。
第二个问题:为什么要有报头呢?
报头的存在是因为我们的发送方和接收方互相传递属性字段的一个非常重要的概念。
就比如你80的爷爷去帮你拿快递,发现快递单上一堆电话后面微信号之类的,他根本不认识这是什么,这叫做不能识别该协议。但是如果你给一个同龄人,他里面就意识到噢这不就是电话尾号吗这是微信号。这是因为年轻人他能够认识我们对应的协议,说明我们之间是有共识的,但是年纪大和年纪小的人就没有共识。
所以同样的,我们两个之间同层协议双方会提前约定好一些共识字段,就有点像我们提前约定好我们这个快递单子的格式,每个格式每个字段分别代表什么含义。订好了之后我们就可以提取里面的字段对我们的数据做解析做处理了。这就叫做协议报头。如果还是不理解,记住一句话,协议报头就是我收到的数据中多出来的那一部分内容就叫做协议报头。
就比如你要给别人发送一个你好,那么你好这个数据就要向下 交付,向下交付的时候,这个你好就要被添加一个应用层的报头。
说白了就是在数据头部呢添加应用层定好的报头。那么应用层继续向下交付到传输层的时候呢,站在传输层的角度,他就把添加了应用层报头的你好数据看作是整体的一个要交付的数据,这时候传输层一看,上层给我添加了一个,数据我也要把我传输层的报头添加进去。然后网络层也添加,链路层也添加。添加完之后再局域网内跑的实际就是加了各层报头的这样一个数据帧。
那么这个过程呢,将自顶向下的这个添加报头的过程叫做封装。比如我们主机1封装了各层的报头,经过我们的局域网通信到了对方主机向上要交付,向上交付的时候。数据链路层呢要将报头跟有效载荷做分离, 这时候就可以通过报头识别出来应该把有效载荷向上交付给哪一个协议。不过上层的协议很多,我怎么知道要交给哪个协议,所以报头内必须要有对应的字段帮我们做这件事情。然后依次去除报头,向上交付,这种自底向上的过程,就叫做解包,有一个好处就是你发出的是你好,最好对方经过解包收到的依然是你好。
封装的本质就是添加报头
解包的本质就是去掉报头并且展开分析。
所以,越靠近上层的报头,他这个报头是越靠近内测的。或者说越靠近底层的他一定是越靠近外侧的。
当前把协议栈理解成一种栈结构,把封装的过程叫做不断的压栈,解包的过程叫做不断的出栈。
那么有没有可能我们数据链路层可能把数据直接给网络层呢,答案是不可能,因为我们的协议之间只能进行同层通信,同层通信呢就说明你定的协议的我也能认识。所以我们的网络通信就可以有另一个全新的视角,就是站在每一层,站在哪一层就说那一层的话,因为同层都只认为自己在和对方在逻辑上直接通信。就比如TCP跟TCP虽然肯定不是直接通信的,但是在逻辑上我们认为我们在直接通信。
回答了上面的问题,这个时候我们就可以回过头来理解。
两台主机是怎么在局域网内通信的?
现在你就应该知道实际是将数据添加应用层报头,再添加传输层报头,在添加网络层报头,再添加链路层报头。到了对端之后,对端会收到我们添加了报头的报文,然后就去掉报头向上交付。
不用多说,两台主机局域网内通信实际就是自顶向下封装和自底向上解包的过程。
这个倒是理解了,不过我是不太理解这个数据是如何从数据链路层从以太网传输给对方的。这个以太网就是局域网,这个横线你就可以把它理解成简单的网线就够了。以太网他的通信原理内实际就是跟我们实际在上课时是一样的,比如我们在上课,有老师和很多学生,老师说,张三,你作业怎么没做,那班级同学们听到了吗?
肯定是听到了,但是只有张三说,老师我没写。张三说的话别的同学听到了吗?肯定的,但是不是对我说的而是对老师说的。相当于我们在众目睽睽之下进行单独的通信,我让张三站起来,张三站了起来,那为什么李四王五赵六田七为什么没有站起来呢?因为你喊得不是我啊,请问,那你怎么知道我没叫你呢?前提是你也收到了这条消息,然后一看喊得是张三,不是喊我。
所以局域网通信就是这一台主机在局域网中进行开麦,每一台主机都有自己的名字也就是mak地址,当我一开麦说D主机你什么是什么,那么其他的ACEFG都听到了,只不过拿主机名跟自己做对比发现不是叫的我直接将报文丢弃就好了。
在局域网之中我们标定一个主机的唯一性,用什么来标定呢?我们用MAC地址来标记,MAC以48位二进制数构成,查看的时候以十六进制显示,MAC地址是一个写入到网卡的地址,在笔记本出场的时候MAC地址就确定好了,单也有虚拟策略帮我们虚拟出网卡或者MAC地址。但是,MAC地址是独一无二用来标定主机的
假设两台主机,还有一台机器路由器,有两个局域网,一个是左侧的局域网,一个是右侧的局域网。它们这两个局域网使用路由器来进行连接,我们路由器最终要将数据从A主机交付到B主机,我们就要有这样一个路由器的存在。
所以A向把数据交给B主机,跟上面是一模一样的,还是先进行自顶向下封装的过程。、
一个问题,A主机能不能把数据之家交给B主机呢?答案是不行!我们A主机无法跨网络把数据交给B主机,从哪可以看出来呢,A主机用的局域网通信标准是以太网的,而B主机的标准是令牌环网的,我们两个的标准都不一样,即便是A把数据包发送给了B那也是鸡同鸭讲。因为A主机和B主机不在同一个局域网,所以他没法直接通信,所以A主机只能交给路由器,因为A和路由器是在同一个局域网的所以可以直接进行通信,而路由器也是一台主机,他也是可以和B主机直接进行通信的,因为路由器和我们的B是在同一个局域网的。换言之,A和B虽然不能直接通信,但是可以经过路由器进行通信。
首先我们现在得花时间理解一个重点的概念,这个概念叫做IP地址,
这个概念交代清除了,那么上面的问题也就能够慢慢去理解了。A主机想把数据发给B主机拿到B主机的MAC地址没有任何用处,因为没有办法直接向B主机直接发送通信,因为我俩不在同一个局域网。
所以A主机拿不到B主机的MAC地址,只能够使用B主机的IP地址。
请问怎么拿到B主机的IP地址,MAC地址都拿不到还拿IP地址这不是扯淡吗。
比如我访问百度腾讯,没有人给你IP啊,实际是你随时随地都有人给你。比如你访问www.baidu.com,这就是个域名,这个域名最终直接被你的浏览器直接进行域名解析,得到你的IP的,所以无论如何你不用担心怎么知道B主机IP的问题,有的是方法。现在假设A主机已经有B主机的IP地址了,所以我们现在就要使用IP来向B主机发消息了,但是,刚刚不是有一个MAC地址吗,这个MAC地址和IP地址有什么关系呢?
举个例子
唐僧就是个路痴,他每次问别人的时候就是,我从东土大唐来,要去西天取经。比如就可能告诉他下一站应该去哪里。现在在女儿国,下一站去黑风岭。所以对唐僧来说,他现在有两套地址,第一套是从哪来到哪去(源IP,目的IP),第二套从女儿国到黑风岭(源MAC地址,下一站MAC地址),这个从东土大唐向西天是一直不会改变的,他为我下一站去哪提供了方向,然后你我现在在女儿国下一站去黑风岭,这叫做我当前在哪里下一站去哪里,这种地址会随着我当前所处的位置一直发生改变这就叫做MAC地址。
那为什么唐僧要去女儿国而不是别的地方呢?是因为我们要去的是西天,所以我必须往西边走,只能去女儿国。
换言之,下一站MAC地址是受目的IP地址影响,根据目的IP要决定我下一站要去哪里的问题。这个当中的每一个地方,就等价与我每经过一台路由器,我跟地方的人说我要去西天,他会告诉我你要去西天的话你下一站应该去哪里,这个的过程就叫做路由的过程。
当我们在进行路由的时候会发现,路由的本质就是根据你的目的地选择下一站去哪里,这就叫做路由。这个路途中你的目的地是不变的,这个目的地给你提供了每一次经过一个中间设备时可以进行路径选择的一个依据这就是源和目的IP地址跟源MAC地址和目的MAC地址之间的区别
首先,我想将数据从A主机发给B主机,那我首先要加上在报文上加上IPB地址,然后传给下层,然后这个报文要去哪呢 ,他要填的比如说路由器的MAC地址,就加上报头MACR,然后交给以太网,虽然A主机跟B主机不在同一个局域网,但是A主机跟路由器在同一个局域网。所以这个报文可以直接提供以太网交给路由器。交给路由器也是向上交付的过程,也要去除报头,去掉后就要将自己的有效载荷交给上层路由器网络层也就是IP层,然后一识别,你不是要去IPB吗?这个IPB刚好跟我是在同一个局域网的,我认识他,那么这个路由器直接就进行把数据要交给这个主机,他交给B主机不是直接交到B主机的网络层,而是向下封装报头,然后就要添加令牌环程序的报头,不管报头是什么反之添加了,然后这个数据经过令牌环就到了B主机了。
要注意的是,数据从A主机刚出来的时候,这个报头添加的是MACR地址,到了B主机的时候,这个报头已经变了但是它的内部没变,还是IPB地址,所以报文通过跨网络传送的时候,IP是不变的 ,但是这里的MAC地址可能会发生变化。那他向上递交的时候又要去掉报头,去掉报头就剩下IPB了,所以这时候我们就发现他在同层协议当中,主机A他发出去的是IPB+数据的报文,路由器他中间路由的时候遇到的也是IPB+数据的报文,主机B最后接收到的也是IPB+数据的报文。
所以在IP以及往上的这些协议看来,我们的数据都是一样的,差异化主要体现在最底层的MAC帧协议,尤其是主机A添加的是以太网的报头,主机B添加的是令牌环的报头,但是这些底层网络的差异就经过了IP地址叫做屏蔽了差异,从IP往上可以看作全部都是同一种网络。所以我们就可以得到一个结论:在TCP/IP协议的网络中,IP及其向上的协议,看到的报文都是一样的。
可以理解成你无论跨了多少网络,无论在哪个设备上,只要在IP层及其往上的协议看来呢,对应的报文呢都是一样的。
就像只要有IP协议的存在,我们在中间路由的时候,向路由器交付时你要脱衣服,在路由器路由完向下时你又要穿衣服,所 以路由器就相当于让我们在不同子网当中进行适配的一个功能。
那么它呢在IP当中,同层的IP呢及其往上看到的都是IP网络,这就是底层网络的差异化就通过IP协议的存在而产生了我们对应的一种虚拟化的一种策略,让所有的主机看到的可以认为都是我们的IP协议,而底层我们可能有各种差别。
这个地方就有点像地址空间这样的概念,让进程以统一的视角去看待内存。就有点像Linux一切皆文件的概念,通过struct file函数指针的方式让所有的上层应用看到的底层的,尽管硬件差别特别大,但我们永远都看到是一切皆文件。
同样的,站在我们的网络当中,有IP的存在呢,同层的协议不管是主机路由器还是别的主机,我们收到的报文都是这种风格的一个IP报头再加有效载荷,而底层差别就是MAC帧的差别。
所以当你向上交付时你就要去掉报头,向下交付你就要重新添加报头。那么无法就是内部不变,更换你的原目的MAC地址的差别。
所以这就引起了我们IP地址 不变,源MAC地址和目的MAC地址一直在变化的原因。
这个地址为什么在变呢?
因为最底层的MAC地址它的报头一直在被替换。好这就是局域网跨网络通信的原理。所以我们以后在通信时,整个数据包在进行走的时候是怎么走的呢?我们现在有两台主机,两个路由器。
路由器能够进行跨网络传输就说明路由器最少也有两个网络接口,要能够级联两个不同的网络,要不然你怎么跨网络转发呢?
所以数据流它是从上层开始向下进行封装添加报头然后经过路径选择将数据进行解包,交给路由器,路由器呢在向下交付,进行封装,在经过封装解包经过路由器,最后到目标主机进行解包向上交付。
所以以后的网络通信只有在两端会走到TCP层之上的协议,在路上它永远都是经过路由器这样这样这样的 。
所以,凡是向上一走他就要去掉报头,重新再一加他就要添加报头,因为第一个主机的MAC地址就被去掉了,而路由器就接收到了然后继续封装添加第一个路由器跟第二个路由器的局域网的MAC地址报头,再由第二个路由器进行解包再进行封装添加第二个路由器跟主机B连接的局域网的MAC地址报头,再递交给B主机,B主机在进行解包,这样无论是在A主机的IP层、第一个路由器第二个路由器、主机B的IP层,拿到的都是同样的报文都是IP+有效载荷的格式。
当我们的底层接收方收到了我们底层的一个数据帧,收到这个数据帧之后,要根据数据帧的以太网的数据首部,就要能够解析出来它的有效载荷应该交付给上层的哪个协议 ,就好比最底层协议收到了一个报文,他把自己报头去掉了,那么下面他就要考虑的第二个问题呢就是自己的报文向上要交给哪一个协议,因为在我们脑袋顶上的网络层呢他可能会存在其他协议,诸如IP协议ARP,在IP再往上还有什么TCPUDP协议,所以每一层协议它都不好过,脑袋顶上都有好多的协议,最后你这个数据的有效载荷交给上层哪一个协议呢?这个就由我们的报头本身来决定,因为报头是发送方填的,对方的报头协议是哪一个协议填的我们向上交付就交付给哪一个协议。
所以在网络通信时,我们有两个共识性的问题
1.报文时要被封装的,如何解包?
2.决定我们的有效载荷交付给上层的哪一个协议的问题?
每一个协议都要考虑这两个问题,当然现在排除最顶层,我们也不知道最顶层有什么协议。所以每一个协议都要有一定的方式解决在两个公共问题。就好比我们未来在学习任何一个协议时,我总会先问这两个问题,报头和有效载荷怎么分离,很简单,一般有的报头是定长的,比如8字节20字节之类的,有的报头它里面带了我们的自描述字段,比如第一个字节,第二个字节,特定一个字节的位置处表示的就是它的报头有多长,甚至还有有效载荷有多长,所以对我们来讲它是添加了我们的自描述字段的。第二种,既然这个报头可以描述有多长,那么它当然也可以里面包含上层这个有效载荷是要交给哪一个协议的。