目录
背景
协议
什么是协议
协议分层
OSI七层模型
TCP/IP模型
网络协议栈与 OS 的关系
网络传输
局域网中直接通信
数据的封装与分用
局域网通信原理
数据碰撞
跨路由器进行远端通信
IP的介绍
传输演示
一开始,计算机都是一台台独立存在的,跨不同主机的业务处理都需要使用拷贝的方式进行,效率低下。
后来,人们将各个计算机连接起来,使用一台服务器对数据集中管理,每个人都能看到共享的数据,进而提升业务处理的速率。
而随着计算机越来越多,人们便通过交换机和路由器进行连接,形成了一个局域网。
随着局域网数量越来越多,最终便形成了当下覆盖全球的广域网。
协议就是一种约定,就像方言一样,只有说话的双方都知道对应的意思,才能在对话中获取信息。
同样,计算机之间的传输媒介是光信号和电信号,通过 频率 和 强弱 来表示 0 和 1 这样的信息,要想传递各种不同的信息, 就需要约定好双方的数据格式。
分层在软件设计中十分常见,具体体现为上层不关心下层的功能实现,只使用下层提供的功能运行。
就那我们打电话为例,我们平时打电话时都是直接认为是在跟对方直接通信的,实际上我们是通过电话提供给我们的接口,才使对方听到我们的声音。至于电话是如何一层一层传到对方耳中的这些过程,我们作为用户并不关心。
而任何一层出现问题并不影响其他层,每层都只关注自己同层的功能,只使用下层的接口。
因此整个系统中,无论上层换了一种语言协议,或是下层换了另一种工具通信,只要满足分层的条件便能够达成通信的结果。
而使用这种分层的结构进行开发,本质上便是为了减少开发者后期的维护成本。
接下来,我们便开始介绍网络对应使用的模型结构,OSI 七层模型又被称为开放式系统互联参考模型。
其为一种框架性的设计方法,最主要的功能使就是帮助不同类型的主机实现数据传输。
它将网络从逻辑上分为了 7 层,自上到下分别为应用层、表示层、会话层、传输层、网络层、数据链路层、物理层。十分完备地展现了网络的结构,但由于其过于复杂,具体层的介绍我们放到 TCP/IP 模型中进行讲解。
TCP/IP 模型在 OSI 七层模型的基础上,将上三层合并成了一层应用层。
说了那么多的东西,那么这个协议栈在哪里?又与操作系统有什么关系呢?相信看了下面这张图,你便会有大致的了解。
可以看到,整个协议栈与操作系统的整个生态高度重合,从某中程度上说,便于操作系统的文件系统类似,放在 Linux 中,我们一样能够使用一切皆文件的思想来看待网络。本质上一样是用户通过系统调用,回调驱动的相应方法,最后硬件进行工作的流程。
但值得注意的一点是,虽然操作系统的种类很多,但是网络(操作系统部分)只能有一种。
两台主机在局域网中是可以直接通信的,就比如以前玩的单机小游戏,能够在局域网中检索,完成开房间的功能。
而两台主机通信的本质实则为两个主机的 OS 与网络协议栈进行通信。
由此可见,两个主机之间的通信都是从应用层出发,逐步向下发送到物理层,传输到了对应主机中再向上交付至应用层,最终使得目的主机收到了我们发送的信息。在这个过程中,每一层都认为是在与对面层直接进行通信。
而通信需要协议,因此每一层都要有自己的协议,其中协议的表现形式体现在协议报头上。
平时我们拿快递的时候,除了商品本身还会有快递单和额外的包装,其中快递单的信息并非传达给用户的,而是给快递员看的。有了这张单子后,快递员才知道收货人的地址,才能够进行配送。因此,在物流体系中,快递单 + 商品才是物流的主体。
同理,在每一层协议中,都需要各自的协议报头与有效载荷。
当一条数据从应用层出发,我们首先为它加上应用层的报头,之后向下传递给传输层,同样将其加上传输层的报头,不断向下传递并加上报头...
最终通过物理层的传输到达了目的主机,首先便是数据链路层拿到对应的报文,将该层的报头去掉后便向上交付。报文被逐步解析,最后对方的应用层便获得了本地传递过去的信息。
经过上面的例子,我们便能够知道,自上而下的处理中每一层都会把上层交给自己的数据作为自己的有效载荷,报头 + 有效载荷就等于自己要发送的报文,这个过程便称为封装。
因为同层之间都能认识对方的报头,因此能做到:
这两个功能便是协议的公共功能,任何协议都要有这两个基本功能。而基于二者,自下而上的处理便称为解包和分用。
假设有一个房间,房间内的人都是位于局域网中的主机,当一个人在喊话时,便可认为他在向局域网中输出信息,每个人自然都会听到这个人说话的声音,但由于叫的不是自己,因此收到的报文还未向上交付时就被抛弃掉了,只有对应的那个人才会将报文交付至应用层并进行处理。
任何人要进行通信,就需要有一个唯一标识符,而网卡出厂时,内部便写入了 sn 号,即 MAC 地址,该地址全球唯一。
若一个人不断在房间里说话或大吵大闹,便会影响其他人接收信息,由此便会发生数据碰撞。
因此,在局域网中,任何时刻都只允许一个人在向局域网中发送消息,以此来避免产生数据碰撞。
首先我们需要了解一下,什么是路由器?
路由器虽然在模型中只占了三层,分别是物理层、数据链路层和网络层,但我们也可以认为路由器是一台主机。
为了达到转发的功能,路由器至少要连接两个子网。
看到这里有的同学就要犯嘀咕了,上面不是刚说操作系统很多种,但是网络只有一种吗?这里怎么又是以太网又是令牌环的?
这是因为数据链路层的标准不同,具体的实现在网卡之中,不同的厂商有不同的实现方式因此会有不同网络的出现,正因如此,我们在上面讲的是,操作系统部分的网络,TCP/IP 这两层的部分才是只有一种的。
当我们准备开始进行数据的传输时,便又遇到了一个问题,局域网中有那么多台主机,我们凭什么将对应的数据交给路由器呢?
我们使用 IP 来标识每一台跨网络的主机,通常我们使用的是 IPv4 的地址,实则为一个四字节的整数。每个字节间用 . 隔开,因此取值范围在 [0.0.0.0, 255.255.255.255] 之间。一般以字符串的形式出现,因此称为字符串风格的点分十进制方案的IP地址。
接着使用结构体位段便能够将一个整形根据字节划分成四个部分的数。
struct ip
{
int part1 : 8;
int part2 : 8;
int part3 : 8;
int part4 : 8;
}
因此,我们这次传输信息在信息的基础上,还要增加一个IP地址表示这个信息要发给谁。
当报文封装到了网络层时,便会进行路由表的查询,借此便可以判断目的 IP (图中简称IPB)与自己是否处于同一个子网中,否则就将报文交付给路由器(默认路由)。
因此,在网络层封装的报头中就会包含我们报文想去的 IPB 这个地址,到了数据链路层,因为我们当前这个报文要先发送给路由器,因此数据链路层的报文则包含了路由器的 MAC 地址。
发送到路由器后,路由器分离出数据链路层的报头,查询路由表后,找到我们目的 IP 的主机,再传递到数据链路层加上对应的报头。不过这次报头里包含的就是目的主机的 MAC 地址了。
因为路由器同时连接两个子网,因此两个传输过程单拎一个出来看的话就是上面讲的局域网直接通信,同时 MAC 地址保证了局域网中只有目的的主机会接收到路由器发送的信息并向上交付,最后对方便得到了我们发送的信息。
在这个过程中,我们会看到网络层使用的地址为 IP 地址,而数据链路层使用的是 MAC 地址,那么这两个地址间有什么区别呢?
可以看到,在传输过程中,我们只使用了一个 IP 地址,至始至终都是指向目的主机的,而 MAC 地址则是根据路径选择的结果来选择下一跳的主机。
因此使用 IP 地址便能够屏蔽底层子网的差异,转发时就会为报文加上对应子网的相应报头,因此当报文传递到路由器时还需要将报文向上交付至 IP 层,才能进一步决定下一步报文发送的方向。