数据在每台计算机中呈现串行的方式传递,如下图:
多台计算机连接在一起,完成数据共享,如下图:
计算机数量更多了,通过交换机和路由器连接在一起。如下图,路由器的左右侧都是一个局域网,两个局域网用路由器连接起来,构成局域网LAN;在局域网内部,对应的主机用交换机可以互相转化消息;跨局域网经过路由器+交换机进行数据转化。数据经过交换机发现不是本网络的,直接交给路由器,路由器再在对应的子网当中,找到对应的主机。
将远隔千里的计算机都连在一起,如下图:
其实我们国家的广域网可以看作一个比较大的局域网。
其实“协议”是一种约定。展开来说,计算机里因为数据经过长距离传输,所以“沟通”的成本会变得很高,例如信息传输的时候衰减是问题,还需要对该数据进行转化,所以经过长距离传输的时候,需要定一些协议的。
例如我们平时见到的摩斯密码、发电报,这种都是一种协议,说白了就是一种约定。也就是通过双方规定的方式,进行信息的沟通。所以通过协议,可以降低沟通信息的成本。
计算机之间的传输媒介是光信号和电信号,通过 “频率” 和 “强弱” 来表示 0 和 1 这样的信息,要想传递各种不同的信息,就需要约定好双方的数据格式。
其实上面的四个问题中,前三个问题是技术问题,而最后一个问题是应用问题。正是有各种各样的问题,所以主机是对称的,也就是发送方有这样的问题,接收方也有这样的问题,所以在我们双方的机器上,在每一层我们都要尝试把每一层的问题解决,所以每一层都要有对应的协议!每层的协议都是各自解决各自当前层的问题。
像(1)问题,是由数据链路层的协议解决的问题;像(2)问题,就是由网络层,也就是IP协议解决的;问题(3)是由TCP协议解决的;问题(4)由类似HTTPS协议解决的。
我们日常在寄快递的时候,通常会有一张快递单号,上面写着的信息其实都是协议,通过双方定的协议,就可以顺利将快递送到另一方中。而这有效的快递单中的信息我们称为报头。那么我们在语言层,该如何描述这些报头信息呢?结构体!所以协议是双方的约定,最终它的表现形式就是结构体对象!
那么只要通信的两台主机,约定好协议就可以了吗?计算机生产厂商有很多;计算机操作系统,也有很多;计算机网络硬件设备,还是有很多。如何让这些不同厂商之间生产的计算机能够相互顺畅的通信呢?就需要有人站出来,约定一个共同的标准,大家都来遵守,这就是网络协议。
我们上面所说的,网络传输过程中会存在各种各样的问题,而且在定义协议的时候问题也错综复杂,所以问题要一个个解决,所以我们把网络协议整体是分层的。
软件为什么要分层呢?相当于是一个很大的项目被分解成了一个个的子项目,最大的好处就是每一层之间的耦合度一定是降低了,也就是高内聚,低耦合;更重要的是可以降低维护成本。
为什么网络协议也是层状的呢?首先网络通信的时候软件项目的规模太大了,所以需要将模块和模块之间解构出来。其次,协议是要解决问题的,而我们的问题有很多,而问题刚好也是层状的,所以协议定义出来也是层状的。
例如我们在打电话的时候,真实的情况是我们人其实在和电话沟通;而在逻辑上,其实我们认为人和人之间在沟通,电话和电话之间在沟通。所以我们人和对方的人进行沟通,就有了语言层;电话和对方的电话进行沟通,就有了通信设备层。我们的人面临着和对方的人准确沟通的问题,电话也面临着和对方电话的沟通问题,所以我们双方都要能够在通信时,为了解决自身问题,结合自身的情况需要定制一些协议。所以当通信设备层出了问题,我们可以直接将通信设备层换成另一套设备,照样不影响上一层正常通话,这就是分层带来的好处。
那么这个网络协议应该是怎么分层的呢?
这七层从底向上分别是:物理层、数据链路层、网络层、传输层、会话层、表示层、应用层。
在 TCP/IP五层模型 中,将 OSI 七层模型中的会话层和表示层归为了应用层这一类,所以分为五层,而我们只学除了物理层的其它四层。
TCP/IP 是一组协议的代名词,它还包括许多协议,组成了 TCP/IP 协议簇。TCP/IP 通讯协议采用了5层的层级结构,每一层都呼叫它的下一层所提供的网络来完成自己的需求。
我们将上面的五层一般称为网络协议栈,由于网络层和传输层在整个网络协议栈中是最重要的,所以我们将这个网络协议栈称为 TCP/IP 协议栈。
网络协议栈和我们之前学的操作系统有什么关系呢?网络协议栈和操作系统的对应关系如下图:
如上图,数据链路层相当于是在各种软件驱动内部实现的。传输层和网络层是在操作系统内部的,所以是要在Linux内核中实现的,也就是内核中的模块。
我们平时获取一个信息,本质上就是用户通过网卡这样的外设,将数据请求,把远端发来的数据信息拉取到本地,本质就是用户在访问硬件。所以网络通信本质上也是在访问硬件!但是我们用户不能直接访问硬件,因为操作系统是硬件的管理者!所以对于用户来说,想要访问网卡,必须要贯穿操作系统,所以操作系统需要为我们提供系统调用!
更重要的是,不仅仅只有一个操作系统是这样子的!不同的操作系统内部实现由它们自己决定,但是不管是什么操作系统,往后实现网络部分的功能时,必须遵守上面的标准!要不然这个操作系统就没办法入网!所以不同的操作系统它的系统内部大部分都不一样,但是网络协议栈必须都是一样的!
两台计算机通过 TCP/IP 协议通讯的过程如下图所示:
在网络通信的时候,应用层是如何把数据发送给对端的呢?每一层都要解决每一层的问题,所以网络协议栈的层状结构中,每一层都有协议!
例如我们需要发送一个信息给对端,除了我们需要发送的信息之外,还需要添加每一层对应的协议信息,每一层对应的协议我们称为报头,报头和信息组合起来我们称为报文,只要对应层的报文发送给了对方,对方就能根据协议正确解析。如下图:
如上图,我们把每一层的报文中的报头去掉后,剩下的称为有效载荷。也就是 报文 = 报头 + 有效载荷。所以通信的过程,本质就是不断的封装和解包的过程!
所以,有以下两个结论:
我们在一个局域网中会有非常多的主机,如果我们把A主机的数据发给B主机,而不是发给C主机,所以原则上每一台主机在局域网上都要有自己唯一的标识符。
在一个局域网中,我们想和某一台主机进行通信,在该局域网中的所有主机都会接收到我们所发的报文,并且对该报文进行解包分用,发现当报头信息不是自己主机时,就会将数据摒弃,只有我们想要通信的那台主机得到数据,进而和我们进行通信,这就是局域网通信,也就是以太网通信。
实际上,我们每一台主机都有自己的 Mac地址,什么是 Mac地址呢?我们所使用的电脑上,都有网卡,每一张网卡在出厂时都会有一个48比特位长度的序列号,这个序列号在全球内都是唯一的,这个序列号信息我们就称为 Mac地址。
在我们局域网进行实际通信的时候,当我们发送信息的时候,数据链路层的报头中一定要包含原 Mac地址和目标Mac地址,这个报文信息我们称为数据帧,整个局域网都会收到这个数据帧,每个主机会对该数据帧进行分离,如果发现报头中的目标Mac地址不是自己当前主机的Mac地址,就会直接丢弃,一旦丢弃了,上层就不会知道曾经收到过这个报文。而如果发现该数据帧的目标 Mac地址 是自己当前主机的地址时,就会将整个报文解析之后,继续交给上一层进行数据处理。
在一个局域网中,如果一台主机正在发消息,周围也有主机正在发消息,此时就会发生数据碰撞问题,一旦发生数据碰撞,所有人的消息也就全部都失效了。所以一旦发生数据碰撞,参与发送数据的主机,都要执行它所对应的碰撞避免的算法。
跨网段的主机的文件传输,数据从一台计算机到另一台计算机传输过程中要经过一个或多个路由器。如果数据从A主机跨网络送到B主机,那么A主机和 B主机中间必须得有路由器这样的设备。
那么数据在跨网路传输的时候,它怎么知道要将数据跨网络到目标主机呢?我们需要引入一个新的地址,叫做 IP 地址,IP 地址能够标识特定一台主机在全网当中的唯一性,那么 Mac地址 不也可以吗?理论上也可以,但是Mac地址 只能应用于局域网,也就是只在局域网中保证它的唯一性,而 IP 地址是要保证在全网内的唯一性的。
那么 IP地址 和 Mac地址 有什么区别呢?我们从用户发信息开始谈起,假设用户需要跨网发一条信息 hello world,像 TCP/IP 协议的通讯过程,在每一层都会添加上对应的报头字段,其中在网络层的报头中,有两个比较重要的信息,就是 srcip 和 dstip,分别表示出发的主机 ip 地址和目的主机 ip 地址。到了数据链路层,如果判断到目的 ip 的地址不在当前子网时,就会将该数据帧交给路由器,而在一个子网内把数据交给路由器,本质就是局域网通信。两个局域网需要通信,就必须要横跨同一个路由器,所以就需要知道路由器的 Mac地址,所以在需要跨网通信的时候,到了数据链路层,就会在对应的报头上的目标 Mac地址 中填上路由器的 Mac地址,说明该数据帧是要交给路由器进行跨网通信的。接下来路由器接收到该数据帧,将报头和有效载荷进行了分离,当路由器识别到该数据帧的目标 IP地址,它就能查到自己的路由表,将该数据帧直接送到对应子网的数据链路层,添加对方子网数据链路层的报头,也就是更新了新的 Mac地址!这次的 Mac地址 是从路由器到新的子网,而原来的 Mac地址 则是从原来的子网到路由器!当该数据帧到对方子网后,就可以继续交给上层的网络层继续读取数据了!可以结合下图理解:
如上图,路由器这个设备可以级联左侧和右侧的两个子网,也就是左右侧都是一个局域网,它们之间互相独立。
所以,IP 协议屏蔽了底层网络的差异化,靠的就是工作在 IP 层的路由器!IP 实现了全球主机的软件虚拟层,一切皆是 IP 报文!
所以得出结论,IP地址 尤其是目的 IP地址,一般都是不会改变的,用来协助我们进行路径选择。而 Mac地址 出局域网后,原 Mac地址 和目的 Mac地址 都要被丢弃,让路由器重新封装!
下面我们重新认识一下数据包在不同层的名字,在应用层一般叫做请求与响应;在传输层一般叫做数据段;在网络层一般叫做数据报;在数据链路层叫做数据帧。