市面上有不少介绍网络是怎么分层的,及每层负责些什么的书,但不多看到有书介绍为何要这么多分层。缓存
本篇将试着从分层是怎么来的这个角度分析一下网络是如何一步一步发展到今天这样的,但愿对网络初学者有所帮助。安全
注意:内容是根据本身已有的网络知识构思出来的,可能跟实际状况有出入,仅供参考。服务器
本文采用TCP/IP详解里的5层结构,即物理层、链路层、网络层、传输层和应用层,而且只讨论以太网和常见的组网方式,不考虑特殊场合的应用。网络
物理层就是如何将多台设备连起来,无论是有线仍是无线的方式,都是让设备之间能交换数据,因此物理上的连通是必不可少的,否则就无法通讯了。性能
若是只有一台设备,就不须要和别人通讯; 两台呢?直接弄根线连上就能够通讯了。操作系统
三台呢,怎么连? 能够像下面这样,三根网线搞定设计
+-------+ +--------->| Node2 |<---------+ | +-------+ | | | ↓ ↓ +-------+ +-------+ | Node1 |<------------------->| Node3 | +-------+ +-------+
四台呢,这么连?code
+-------+ +---------->| Node2 |<----------+ | +-------+ | | | ↓ ↓ +-------+ +-------+ | Node1 | | Node3 | +-------+ +-------+ ↑ ↑ | | | +-------+ | +---------->| Node4 |<----------+ +-------+
虽然四根网线搞定,但带来至少两个问题:dns
Node2和Node4之间怎么通讯? 首先确定得通过Node1或者Node3,就算能根据网络繁忙程度进行智能的选择,Node1和Node3也须要把部分精力用在帮忙转发数据包上,就算转发消耗的系统资源能够忽略不计,但Node1和Node3之间的通讯呢?因为带宽有限,Node1和Node3之间的通讯确定会受Node1或者Node3之间通讯的影响。想象一下,寝室里面有四我的,A和C之间传一个电影,致使B和D之间打局域网游戏卡的要死,你说B和D恼火不?游戏
Node2和Node4关机以后,Node1或者Node3之间就无法通讯了,也就是说若是这个环里面有两台设备下线,那么就会变成两个单独的网络
改进成这样呢?
+-------+ +---------->| Node2 |<----------+ | +-------+ | | ↑ | ↓ | ↓ +-------+ | +-------+ | Node1 |<----------+---------->| Node3 | +-------+ | +-------+ ↑ | ↑ | ↓ | | +-------+ | +---------->| Node4 |<----------+ +-------+
确实解决了上面的那两个问题,新的问题出现了: 一台电脑要连三根网线,总共是3+2+1=6根网线,看起来还好,但想象一下有10台机器,那就是10+9+8+7+6+5+4+3+2+1=55根,根本无法想象应该怎么布线。
很明显这种只靠网线的办法在局域网中就行不通,更别说将世界上全部设备互联了。
因而人们想到引入一种新的设备,用来负责链接各个机器,机器只要和这个新的设备打交道就能够了,因而有了下面这样的链接方式:
+-------+ | Node2 | +-------+ ↑ | ↓ +--------+ +-------+ | | +-------+ | Node1 |<---->| Device |<---->| Node3 | +-------+ | | +-------+ +--------+ ↑ | ↓ +-------+ | Node4 | +-------+
这样看起来就简洁多了,而且往这个网络中添加机器也很是简单,牵一根线到中心的那个设备就能够了。固然这样的组网也有缺点,那就是中心的那个设备挂了后,整个网络就不通了,因此中心设备的功能必定要越简单越好,这样就能保证其稳定性。
其实上面的这两种链接方式就是咱们常说的环形网络和星形网络,环形网络不常见,只在某些特殊场合使用,而星形网络就是咱们如今常见的组网方式。
有了星形网络后,物理链接上没问题了,那么接下来的问题就是怎么通讯,Node1要发数据给Node4,确定要先发给中间的Device,那么Device怎么知道要发给Node4,而不是Node3呢? Node1和Node3都给Node4发数据,Node4怎么区分数据是谁发过来的呢?这时候链路层就登场了。
为了解决上面物理层遇到的问题,聪明的人们设计了一种链路层协议,叫以太网协议。
由于机器之间要经过网线通讯,那么每台机器上都有一个处理数据传输的硬件,这个硬件就是网卡,在以太网协议中,要求每一个网卡都要有一个地址,就是咱们常说的网卡(mac)地址,而且这个地址必须惟一,不能冲突。
为了解决网卡地址惟一这个问题,人们将网卡地址拆成两个部分,第一部分是厂商的ID,另外一部分由厂商本身控制,因为厂商的ID是惟一的,因此只要厂商本身不生产一样mac地址的网卡,那么全部厂商的网卡地址都将惟一。
有了mac地址后,Node1给Node4发的数据包中就能够带上各自的mac地址,这样就能惟一的标识这个包是由谁发给谁的了,这样的数据包就是以太网数据包,固然以太网协议还有其它的字段,但这两个字段是最重要的。
如今知道数据包是由谁发给谁的了,另外一个问题来了,中心的那个Device收到Node1发给Node4的包以后,怎么知道Node4是链接到哪一个端口上的呢?
最开始人们采用了一种简单粗暴的方法,那就是群发,因为中心的那个Device不知道Node4链接到哪一个端口的,那么它就会将数据复制多份,向全部端口都发一份(Node1所在的端口除外,由于Device知道数据包是从这个端口发进来的),这样Node4就收到了Node1发过来的数据,固然其它两个Node也会收到相应的数据包,但网卡很老实,发现不是发给本身的数据包,就不看包里面的内容,直接把数据包丢弃了。
上面这种简单粗暴的设备就是咱们常说的集线器(Hub),从它的工做方式咱们能够看出它有两个缺点:
数据不安全: Node1发给Node4的数据会被发送到Node2和Node3上去,虽然网卡默认状况下会丢弃该数据包,可是也能够设置网卡为混杂模式,从而能够接收并处理这些数据包。
性能差: Node1跟Node4通讯的全部数据包都要发给Node2和Node3一份,一方面增长Device的压力,而且还要占用和Node2及Node3之间的带宽
为了解决集线器的问题,人们发明了交换机,跟集线器相比,交换机里面多了一张转发表,里面包含了mac地址和端口的对应关系,大概以下:
mac地址 | 端口 |
---|---|
02:42:83:06:75:13 | 2 |
08:00:27:03:d0:e7 | 2 |
ee:35:41:bb:a4:60 | 3 |
02:42:34:8F:0E:FE | 4 |
上表中,02:42:83:06:75:13和08:00:27:03:d0:e7链接在交换机的2号端口,ee:35:41:bb:a4:60链接到3号端口,02:42:34:8F:0E:FE链接到4号端口。
这里02:42:83:06:75:13和08:00:27:03:d0:e7都与端口2相连,表示与端口2链接的是一个交换机或者有多个虚拟网卡的主机。
有了这张表以后,交换机收到数据包以后,就知道要从哪一个端口发出去了,因而解决了集线器的那两个问题,那么这里又有一个问题,这张表示从哪里来的??
交换机在刚启动时,这张表是空的,当收到第一个数据包的时候,它也不知道要从哪一个端口转发出去,因而它采用和集线器同样的方式广播出去。当交换机每次从一个端口收到数据包时,都会提取数据包里面的源mac地址,而后将这个mac地址和端口的对应关系添加到(或者更新)转发表,这样很快就会将转发表构造起来,就算有网线换了端口,也会及时的更新转发表。
有了交换机后,局域网是搭建起来了,可是能够经过N个交换机将世界上的全部机器都连起来吗?就像下面这样:
+---------+ | | +-------+ +-------+ | Switch3 |------->| Node5 | | Node2 | | | +-------+ +-------+ +---------+ ↑ ↑ | | ↓ ↓ +---------+ +---------+ +---------+ +----------+ +-------+ | | | | | | | | +--------+ | Node1 |<---->| Switch1 |<---->| Switch2 |<---->| ....... |<---->| Switch N |------->| Node N | +-------+ | | | | | | | | +--------+ +---------+ +---------+ +---------+ +----------+ ↑ ↑ | | ↓ ↓ +-------+ +-------+ | Node3 | | Node4 | +-------+ +-------+
答案是否认的。虽然每一个Node都有一个惟一mac地址(UUID),但这个UUID里不包含任何其它信息,这给数据的全网传输带来了很大的问题。
想象一下咱们每家每户都用一个UUID来标识,没有咱们如今用的地址和邮编,那么把我家的地址给你,叫“912FAD50-07B2-4FBA-8F65-4537ABEF5670”,请问你要怎么找到我家?若是咱们是一个村的人,那还不是特别难,村委会把全部住户的UUID都收集起来,找人的话去村委会问就好了,若是咱们不在一个国家呢?这下很差办了,要不你家村委会特别强大,知道世界上全部住户的UUID,而后告诉你下一步再去哪里问,要不村委会没这能耐,只能告诉你去镇上问,镇上再让你去市里问,最终问到一个可能相似叫国家信息中心的地方,它告诉你地址是在美国(假设目的地是美国),因而你得去美国的国家信息中心去问,把相关的人问了个遍终于知道了我在哪里。
上面的方法看起来最终也能找到,那问题在哪里呢?简单的列几条
如今世界上联网的设备大概有几十亿,而且每一年还在疯狂的增加。要有一个机制来管理全部的这些UUID,而且能高效的在里面找到想要的数据,这几乎是不可能的,交换机的转发表都会很是大,性能确定跟不上
如今移动设备已经占据了很大的份额,位置老变来变去,意味着由UUID构成的网络拓扑结构老在发生变化,那怎么能保证及时的将地址变化状况更新到那些管理机构呢?估计光更新的请求就把网络给撑爆了
没隐私,走到哪里都是那个UUID,都有人知道你在哪里,恐怖不?
因此在实际操做中这种办法根本不可行,就像邮局没法根据你提供的UUID找到你家地址同样。这个时候就须要一种相似于“湖南省长沙市岳麓区xxx路xxx号”的东西,因而网络层的IP登场了。
网络层的IP地址就是咱们想要的相似于“湖南省长沙市岳麓区xxx路xxx号”的东西。
对于生活中的地址,好比说湖南,为何要叫这个名字,为何管理的范围是如今这样?国家层面说了算(固然不是瞎说,根据历史状况来定),湖南下面要分几个市呢?湖南省本身进行划分。地址一旦规划好,就很稳定,不多变,变化的时候就是合并行政村、撤县设市、设置直辖市啊之类的。
IP地址也差很少,一旦分配好了就不会常常变化,好比给湖南分了那么多的IP段,那么就不会频繁的变化,一直都是湖南的;惟一不一样的是生活中的地址没有长度限制,而IP地址有长度限制,IPv4的地址范围只有40亿左右(当时设计的时候以为够用了,结果如今悲剧了...)。
既然资源有限,那么就有分配的问题,先到先得,因为欧美发达,上网的人多,因此申请比较积极,抢去了大部分的地址空间,像非洲这样的,就只抢到不多的份额。地址分配机构也是一级一级的,好比我是中国电信公司,须要大批的IP,那么我就去向负责亚太地区的机构去申请,若是机构发现如今有多余的,就会直接分配地址给我,若是没有那么多,它会向它的上级要资源,因此这事和申请域名、通讯频道是同样的,申请必定要积极,否则就被别人抢去了,等拿到分配给个人IP地址段后,就能够一级一级的往下再分配下去了,内部怎么分就看本身怎么管理了。
如今再去申请IPv4已经没戏了,2011年IPv4地址就被分配完了,如今该抢IPv6了,不过IPv6地址空间大,不必那么急着抢,而且也不是谁都能申请,想申请都少就能申请多少的,只能按需申请,再说也不是免费的。
为了简化讨论,这里讨论的IP地址都是IPv4公网地址,不考虑内网地址,不考虑NAT转换的状况。同时因为网段的划分和路由是个很复杂的过程,在这里不讨论路由表是如何构造并更新的。
有了IP地址以后,咱们就须要一个能转发IP数据包的设备,那就是路由器,有了路由器以后,咱们的网络就变成了这样:
+---------+ | | +-------+ +-------+ | Switch2 |<------>| Node4 | | Node2 | | | +-------+ +-------+ +---------+ ↑ ↑ | | ↓ ↓ +---------+ +---------+ +---------+ +----------+ +---------+ +-------+ | | | | | | | | | | +--------+ | Node1 |<---->| Switch1 |<---->| Router1 |<---->| ....... |<---->| Router N |<------>| SwitchN |<----->| Node N | +-------+ | | | | | | | | | | +--------+ +---------+ +---------+ +---------+ +----------+ +---------+ ↑ ↑ | | ↓ ↓ +-------+ +----------+ | Node3 | | Node N+1 | +-------+ +----------+
有了IP地址后就很容易路由了,原理跟投递邮件如出一辙,想象一下投递邮件,假设你在上海,要写一封信给北京的朋友,首先得找到最近的邮局,把信投进去,信封上会填上收件地址和发件地址,而后会有工做人员将信件发到下一站,下一站会有工做人员接手再发给下一站,通过几回中转到了上海总站,而后由上海总站再发往北京总站,北京总站再派工做人员一级一级的下发,最终将信件送到你朋友手上。
再来看看网络中的数据包,假设上海的A要给北京的B发一个数据包,首先得根据他本身的路由表(由本身配置)和B的地址,找到最近的路由器(这就跟上面找邮局是同样的,路由器就至关于邮局),路由器会根据它的路由表将数据包再往外发,多是先到上海的某个中心路由器,而后再由它发给北京的路由器,最后由北京的路由器一级一级的往下发,最终到B的手中。
咋一看好像也是一级一级的转发,那跟前面被否决的链路层交换机的转发有什么不同呢?
路由器里的路由表要小不少:IP是一段一段的有范围的,整个中国的IP段可能也就几百条,这几百条再被各个省分红不一样的小的IP段,那么全部省一级的IP段总共加起来也差很少万条的级别,跟几十亿级的设备数量来比要小多了。而且IP范围和生活中的地址是同样的,不怎么变化,不须要频繁更新。
IP地址的位置是固定的,不须要频繁更新:移动设备就像是城市里的流动人口同样,人会常常租不一样的房子,但房子自己的地址不会发生变化,就是说移动设备换地方后会换IP地址,但IP地址所关联的路由器是不会变化的,即IP地址在整个网络拓扑中的位置不会变化,变化的是设备的位置。
更好的隐私:因为你们都用IP通讯,而IP没有和具体的设备绑定,给你一个IP地址,你只知道它大概位置在哪里,但你不知道用这个IP上网的设备是什么(固然能够经过其它的手段知道,但根据IP无法知道)。
你们都经过IP地址来通讯,但交换机只知道链路层,不知道IP层的任何信息,因而设备在向另外一个设备经过IP地址发送数据以前(经过交换机直接相连的两台机器),须要知道对方的mac地址,这个时候就用到了ARP协议,利用该协议,能够根据IP地址获得mac地址,固然,该协议只在局域网内有效,网络中的每台设备只和当前局域网的另外一台设备直接通讯,想要访问其它网络中的设备,须要当前网络中的其它设备代为转发,具有转发IP数据包功能的设备,咱们就说它具备路由功能,通常就是咱们常说的路由器。
IP网络这么好,那咱们还须要链路层的网络吗?直接经过IP进行通讯就行了,还要mac地址干吗?答案是不行,仍是得依赖链路层。由于IP地址是逻辑上的东西,因此就要考虑分配问题,一台设备加入了当前网络,给它分配个什么IP好呢?机器数量少且不怎么变化的状况下,能够人工管理,作到地址不冲突,但在公共场合呢?你去了机场,连了机场的网络,IP怎么办?机场工做人员给你找一个空闲的填上?就算机场有那闲功夫,专门派我的或者设备显示当前网络还有哪些IP是空闲的,你也烦啊,须要找到这我的或者设备,而且还要本身手动配置网络IP;再考虑一种状况,你坐在地铁上,从闵行区到杨浦区,中间要通过徐汇区,在闵行区的时候你手机是在闵行区的网络里,等地铁通过徐汇区的时候,你连上了徐汇区的网络,IP地址咋办,到哪去找一个没被人占用的IP地址?那么多的人,怎么保证不冲突?到了杨浦区的时候,又得人工切换,估计你都要崩溃了。因此网络层仍是离不开链路层来完成一些它的管理工做。
有了ARP后,系统在手工设置本身的IP以前,能够经过ARP请求来问问当前局域网里面有没有一样IP的机器,这样就能够有效的避免IP冲突。
同时为了动态的分配IP,人们想出了DHCP协议,大概过程就是,当一个机器连进网络的时候,先广播一下,问当前局域网有没有人能够分配一个IP给它,当前网络中的DHCP服务器收到请求后就会分配一个空闲的IP给请求的机器,应答包中还包含了子网掩码和默认网关。有几个问题须要注意:
因为当前机器没有IP,因此只能依靠链路层的广播机制,因此它的范围局限于当前局域网(固然局域网的其它设备也能够转发该DHCP请求出去,从而实现跨网段的DHCP)
当前局域网只能有一个DHCP服务器,不然两个服务器管理的地址可能冲突
在有DHCP服务器的网络中也能够手动的给本身配置IP,只要不使用被DHCP服务器管理的IP范围,而且不和别人冲突就能够了
IP层解决了将一个包从一地址发到另外一个地址的问题,但这个数据包是给谁的呢?
在生活中,一个地址多是一个家庭住址,或者是一个公司,邮件中除了包含收件地址和发件地址以外,还须要收件人和寄件人的信息,由于只有有了收件人的名字,才知道把邮件交到谁的手上。
网络世界中也同样,网络(IP)层负责将数据包发到目的地址,但这个数据包是给谁的呢?机器上运行那么多的进程,哪个才是接收者呢?就须要一个东西来区分这些进程,因而就有了端口的概念,若是进程须要网络通讯,就向操做系统申请一个端口,经过这个端口来惟一标识这个进程。
注意:端口是个抽象的逻辑概念,并非说机器上有那么多的硬件端口。
这个时候UDP就登场了,它在IP协议的基础上增长了源端口和目的端口字段,这样一个UDP包就能惟一的肯定是从哪台设备的哪一个进程发给哪台设备的哪一个进程。
有了UDP,就能将包发送给指定设备上的进程,目的进程也能经过收到数据包中的源地址和端口,发送应答包回去。那这样是否是就搞定了呢?
想一想发邮件,是否是有邮件丢失的状况,丢失了会怎么样?丢失后形成的状况是接收方没收到邮件,发送方也不知道邮件丢了。为了应对这种状况,邮局推出了挂号信,就是若是邮件丢失,会通知发送方。
UDP也有这样的问题,当线路繁忙的时候,路由器若是处理不过来就会将收到的包丢弃,这时目的端收不到数据包,发送端也不知道数据包丢了,因而形成通讯故障。这个时候TCP就登场了,它在里面增长了一些收包确认及超时重传的机制,保证数据包能完整的发送到目的地。
就如同挂号信比平邮要贵同样,TCP要比UDP的开销大,因此对于能够接受丢包的场合,UDP仍是有一席之地。
经过传输层,数据包已经完整的发送到了接收进程手中,那么数据包里面包含了什么数据呢?应该怎么解析它呢?
想一想邮件,收件人收到以后打开邮件会看到什么?多是一封普通的问候信,也多是一首诗,有多是中文的,也有多是英文的。总之要有必定的格式,而且是收件人能看懂的格式,不然这封信就没有任何意义。
一样的,收到数据包的进程打开数据包以后也须要能看懂数据包的内容,否则该数据包就没有任何意义,数据包的数据要能被看懂,那就得必须有固定的格式,这种格式就是咱们常说的应用层协议,如ftp、http、dns、snmp等。发送方必须发送接收方能识别的协议格式,好比向http服务器只能发送http请求,若是发ftp请求过去的话,http服务器就不认得,无法处理,只能返回错误。
数据发到目的进程手上了,目的进程也能看懂数据的内容,因而一个成功的通讯过程就完成了。
这里以一个dns请求为例,描述一下数据包的传输过程,由于dns默认是udp协议,因此比较直观。
假设dns服务器的IP是8.8.8.8,端口是53
应用层构造一个DNS包,而后告诉UDP层发到8.8.8.8的53端口
UDP层收到包后,构造一个UDP包,里面的数据就是DNS包的内容,目的端口是53,源端口由操做系统分配一个(或者能够经过绑定的方式本身指定一个),而后告诉IP层让它把这个UDP包发给8.8.8.8
IP层收到请求后,就去查询路由表,看这个包应该怎么出去
在这种状况下,因为8.8.8.8跟本身不在一个子网,因而会找到默认网关的IP,同时获得本身应该用哪一个IP及哪一个网卡发包出去;这里假设咱们只有一个网卡eth0,IP为192.160.64.12。
构造一个IP包,里面的数据是UDP的内容,目的IP是8.8.8.8,源IP为192.160.64.12
构造ARP数据包,源地址为eth0的mac地址,目的地址为链路层广播地址,广播局域网,得到网关IP对应的mac地址
通知链路层将这个IP包发给网关对应的mac地址
链路层收到请求后,构造以太网包,目的地址为网关的mac地址,源地址为eth0的mac地址,内容为上面构造的IP包,而后发送给网关
网关收到数据包后,一看目的IP是8.8.8.8,跟本身不在一个子网,因而就查看本身的路由表,而后将数据包发给下一个路由器(发给下一个路由器的过程和上面的6~8步相同)
直到这个数据包到了最后一个路由器,该路由器发现8.8.8.8跟它其中的一块网卡在同一个子网,因而经过那块网卡直接发给8.8.8.8(发给8.8.8.8的过程和上面6~8步中发给网关的过程相同,只是目的地由网关变成了8.8.8.8)
8.8.8.8收到数据包一看,发给53端口的,因而就转给了DNS服务器进程
DNS服务器进程读取包的内容后,构造应答包,而后根据源IP和源端口,跟请求包同样的流程,将应答包发给了请求方
系统有ARP表,会将查到的IP地址同mac地址的对应关系缓存起来,因此上面的过程当中并非每次都要发ARP包
本篇只介绍了最最最基本的网络知识,但愿对初学者有帮助,后续有机会再一一介绍其它的。