目录
一、计算机网络背景
1.1 网络发展
1.2 "协议"由来
二、网络协议初识
2.1 协议分层
2.2 OSI七层模型
2.3 TCP/IP五层模型
三、网络协议栈
四、数据包封装与分用
五、网络传输基本流程
5.1 同局域网的两台主机通信
5.2 跨网络的两台主机通信
六、网络中的地址管理
6.1 IP地址
6.2 MAC地址
独立模式:计算机之间相互独立
在早期,计算机之间相互独立,此时若多个计算机要协同完成某种业务,那么就只能等一台计算机处理完后再将数据通过光盘等硬件传递给下一台计算机,然后下一台计算机再进行相应的业务处理,效率非常低下
网络互联:多台计算机连接,完成数据共享
这时就有人设法将这些计算机连接在一起,当某个业务需要多台计算机协同完成时,就可以将共享的数据放到服务器中进行集中管理,此时各个计算机就都能获取到这些共享的数据,所以各个业务在处理就能随时进行切换了
局域网LAN:通过交换机和路由器将多台计算机连接
后来这样的网络雏形逐渐发展,连入这个网络中的机器越来越多,于是就出现了局域网的概念
在局域网中有一种设备为交换机,交换机主要完成局域网内数据的转发工作,即在局域网内将数据从一台主机转发给另一台主机。各个局域网之间通过路由器连接起来,路由器主要完成数据的路由转发工作
广域网WAN:将远隔千里的计算机连接
各个局域网之间通过路由器相互连接在一起,便组成了一个更大的网络结构,被称为广域网。实际局域网和广域网是一种相对的概念,广域网也可以看作一个较大的局域网
还有类似于城域网和校园网的概念,城域网实际就是在一个城市范围内所建立的计算机通信网,而校园网对应的就是校园范围内所建立的计算机通信网。城域网和校园网实际都是一种相对的概念,都可以将其看作一个较大的局域网
"协议"本质就是一种约定,通信双方只要曾经做过某种约定,之后就可以使用这种约定来完成某种事情。而网络协议是通信计算机双方必须共同遵从的一组约定,只有将这种约定用计算机语言表达出来,此时双方计算机才能识别约定的相关内容
如通信计算机双方曾经做过如下约定:
上图为一个位段结构,可以通过位段来表示某种协议规定的,而实际上计算机网络里面的协议报头就是通过位段来实现的
有了约定后,当甲计算机向乙计算机发送类似于{1, 0x1234}的数据时,乙计算机识别到code的值是1,于是就知道了甲计算机是让自己将data的值存储进数据库(纯软件的约定方案)
计算机之间的传输媒介是光信号和电信号,通过"频率"和"强弱"来表示0和1这样的信息,因此要想传递各种不同的信息,就需要约定好双方的数据格式(纯硬件的约定方案)
网络协议栈设计成层状结构,其目的就是为了将层与层之间进行解耦,保证代码的可维护性和可扩展性
如在打电话时,站在工程师的角度实际这两个人并不是直接进行沟通的,而是甲的电话将甲说的话记录下来,经过一系列编码转码后,通过通信网络将信息从甲的电话传递到了乙的电话,然后信息在乙的电话中再经过对应的编码转码,最后乙才通过话筒听到了甲所说的话
其中,人与人之间通信使用的是汉语,可以将其称为语言层;而电话和电话之间通信使用的是电话系统相关的一些接口,可以将其称之为通信设备层
后来随着科技的发展,开始使用智能手机,此时下层使用的通信设备变化,或是手机卖到了其他国家,此时上层使用的通信语言变了,但仍然可以正常沟通
分层的益处在于"封装",在分层情况下,将某层的协议进行替换后,通信双方之间不会受到影响
实际上,在设计协议栈时也可以不进行分层,将各个层的功能全部写在一起,将这些小模块合并成一个更大的模块。但这样的设计方式对设计人员的要求就非常高了,设计人员必须能够编写从物理层到应用层的整个通信过程的代码,并且最终设计出来的代码的可维护性和可扩展性是很低的
层状结构的本质是软件工程上面的解耦,此时层与层之间只有接口的相互调用关系,此时就可以让研究不同领域的开发人员编写不同层的代码,最后再将各层的代码联调起来,由于每一层的代码都是对应领域的专业人员编写的,因此代码联调后整体的性能也是很高的
并且这样的层状结构可以增加代码的可维护性和可扩展性。比如有一天觉得数据链路层的代码已经无法承担起通信的能力了,那么此时就可以用一个新的协议对它进行替换,而其他各层对应的协议都不用换,即可扩展性。而若协议栈的某一层出现了问题,只要确定了是哪一层出了问题,就可以直接去对应层去找问题,即代码的可维护性
最开始指定的协议为OSI七层协议
TCP/IP是一组协议的代名词,还包括许多其他协议,共同组成了TCP/IP协议簇。TCP/IP通讯协议采用了五层的层级结构,每一层都呼叫其下一层所提供的网络来完成自己的需求
下面几层几乎没有区别,操作系统对应的是传输层和网络层,数据链路层和物理层都是对应在驱动层的,而TCP/IP协议当中的应用层就对应到OSI七层协议当中的应用层、表示层和会话层
但并不是绝对的,如现在很多交换机也实现了网络层的转发,很多路由器也实现了部分传输层的内容(比如端口转发)
集线器了解
电磁信号在长距离传输过程中信号是会衰减的,而集线器的主要功能就是对接收到的信号进行再生整形放大,以扩大网络的传输距离,同时把所有节点集中在以它为中心的节点上
集线器属于纯硬件网络底层设备,基本上不具有类似于交换机的“智能记忆”能力和“学习”能力,也不具备交换机所具有的MAC地址表,所以发送数据时是没有针对性的,而是采用广播方式发送,即当集线器要向某节点发送数据时,不是直接把数据发送到目的节点,而是把数据包发送到与集线器相连的所有节点
通常在手机或者电脑上使用的APP,如抖音、快手、淘宝等,这些APP都是在应用层的。用户在应用层的各种请求最终会下达给操作系统,操作系统内除了进程管理、文件管理、内存管理、驱动管理之外,还有一个内嵌的软件协议栈,协议栈将用户的数据进行各种封包后,通过网卡将数据传递到网络当中,数据在网络内部经过各种路由转发,最终将数据传送到了目标服务器
目标服务器本身也是一台计算机,假设该计算机的操作系统就是Linux,而访问目标服务器时使用的可能是Windows、安卓或者IOS等操作系统。此外,对端服务器也有自己的协议栈,对端服务器将拿到数据通过协议栈进行各种解包操作后上交给应用层,在对端服务器的应用层就有一个对应的软件服务器,如抖音服务器、快手服务器、淘宝服务器等,软件服务器内部对收到的用户请求进行各种分析处理后,再将对应的数据以相同的方式返回给用户
不同操作系统的进程管理、文件管理、内存管理、驱动管理的实现方式可能是不一样的。如Windows和Linux实现多线程的方式就是不一样的,Linux中的线程是用轻量级进程模拟的,而Windows中是有真正意义上的线程的
而协议栈是网络标准组织定义的,是具有全球性质的,所有的操作系统都必须支持。虽然客户端和服务端可能使用的是不同种类的操作系统,但每个操作系统实现网络协议栈的方法包括各种细节都是一样的,因此双方对数据进行的封包和解包操作基本一致
网络协议栈
操作系统与网络协议栈有着密切的关系。网络协议栈主要负责数据的通信,其自顶向下可分为四层,分别是应用层、传输层、网络层、数据链路层
网络协议栈各层所处位置:
有些地方可能将网络协议栈分为了五层,多了最底层的物理层,物理层主要就是利用传输介质为数据链路层提供物理连接,实现比特流的透明传输,是与硬件强相关的
有的书还会将数据链路层和物理层统称为网络接口层,也有书会将网络层称为网际层
网络协议栈各层功能
要实现通信首先要能够将数据发送出去,而数据链路层和物理层就是负责数据真正的发送过程的
在数据链路层和物理层的支持下,现在能够将数据发送出去了,但是还应该知道数据应该往哪里发,而网络层完成的就是数据转发,解决了数据去哪里的问题
有了发送数据的能力,也知道数据应该往哪里发,但是并不能保证发出去的数据能够成功的到达对端主机,比如在传输过程中可能会出现丢包或对端主机关机,甚至对端服务器出错,导致数据传送出现问题。而传输层的工作就是处理传输时遇到的问题,主要是保证数据可靠性
即网络协议栈的下三层能够保证把数据交付给对端主机,但现在还需要明确的是,将数据发送给对端主机的目的是什么,而这就是应用层要解决的问题。应用层需要根据特定的通信目的,对数据进行分析与处理,以达到某种业务性的目的
网络协议栈的下三层主要的完成的工作就是处理通信细节,而应用层主要完成的就是某种具体的业务细节
数据封装的过程:
数据分用的过程:
报头
报头本质也是一种数据,报头一般是通过位段实现的,因此协议栈的每一层都有一个对应的位段来表示当前层的报头
有效载荷
当对端主机收到数据后,需要自底向上贯穿协议栈,依次进行数据的解包与分用。在这个解包的过程中,每一层的协议只需要提取出数据中对应的报头,然后对该报头进行分析处理,而剩下的数据则直接交付给上层即可
因为每一层的协议只关心数据中与当前层对应的报头信息,而剩下信息的具体内容根本不必关心,数据中除当前层的报头以外的数据就被称为"有效载荷"
上层协议在数据封装时添加的报头信息,在下层协议进行数据解包时看来就是有效载荷。比如数据封装时应用层添加的报头信息,在对端主机进行数据解包时,在对端主机的传输层、网络层以及链路层看来,该应用层曾经添加的报头信息就是有效载荷
如何将报头与有效载荷进行分离?
协议栈的每一层都要从数据中提取对应的报头信息,而要将数据中的报头提取出来,首先就需要明确报头与有效载荷之间的界限,这样才能进行分离。而每一层添加报头时都是将报头添加到数据的首部的,因此只要知道了报头的大小,就能够讲报头和有效载荷进行分离
获取报头大小的方法通常有两种:
每个协议都要提供一种方法获取到报头的大小,这样才能在解包时将报头与有效载荷进行分离
当前层如何知道应该将有效载荷交付给上层的哪个协议?
网络协议栈的每一层都可能会对应多种协议,即便将报头与有效载荷分离了,那当前层应该将有效载荷交付给上层对应的哪个协议呢?实际在每种协议的报头当中,几乎都会包含一个字段,表明我们应该把分离出来的有效载荷交付给上层的哪个协议,这就是分用的过程
协议共性
在解包时必须将报头与有效载荷分离,在分用时必须知道应该将有效载荷交付给上层的哪个协议
同一个局域网内的主机是能够直接进行通信的,因为最初局域网设计的目的,就是为了让局域网内的主机能够进行通信
当用户要将文件传输给另一台主机前,该文件数据需要先通过网络协议栈进行封装:
数据封装完毕后就可以通过局域网将其发送给对端主机了,而当对端主机收到数据后,对应也需要通过网络协议栈对该数据进行解包与分用:
任何一台主机在发送数据之前,该数据都要先自顶向下贯穿协议栈来完成数据的封装,在这个过程中,每一层协议都会添加上对应的报头信息;而任何一台主机收到数据后,都要先自底向上贯穿协议栈来完成数据的解包和分用,在这个过程中,每一层协议都会将对应的报头信息提取出来
局域网内传输数据时,该局域网内的所有主机都能收到
在一个局域网当中,除了当前正在进行通信的A主机和B主机以外,还有其他的主机
实际当主机A想要发数据给主机B的时候,该局域网内的其他主机也都收到了该数据,只不过除了主机B以外,其他主机识别到该数据并不是发给自己的,此时其他主机就把收到的数据丢弃了
即在局域网(以太网)通信时,该局域网内所有的主机在底层其实都收到了所有数据,只不过经过筛选后只提交上来了发给自己的数据
碰撞
主机A在向主机B发送数据时,其他主机彼此之间可能也正在进行通信,甚至主机A在和主机B通信的同时也在和其他主机进行通信
但同一局域网中的所有主机在通信时,使用的都是一个共同的通信信道,因此若局域网内的多台主机同时进行通信,此时这些数据之间就可能会相互干扰
每一个局域网都可以看作是一个碰撞域,若某个主机发送出去的数据与其他主机发送的数据之间产生了干扰,我就称这两台主机在该碰撞域中发生了碰撞
如何判断发送出去的数据是否发生了碰撞?
因为发送到局域网当中的数据是所有主机都能够收到的,因此当一个主机将数据发送出去后,该主机本身也是能够收到这个数据的。当该主机收到该数据后就可以将其与之前发送出去的数据进行对比,若发现收到的数据与之前发送出去的数据不相同,则说明在发送过程中发生了碰撞
发生碰撞后如何处理?
当一个主机发现自己发送出去的数据产生了碰撞,此时该主机就要执行"碰撞避免"算法。"碰撞避免"算法实际很简单:当一个主机发送出去的数据产生了碰撞,那么该主机会随机等一段时间后,再重新发送该数据
实际在网络通信压力不大的时候发生碰撞的概率是不大的,不要小瞧计算机的处理速度,也不要小瞧网线传播数据的速度
每个主机如何判断该数据是否是发送给自己的?
在局域网中发送的数据实际叫做MAC数据帧,在这个MAC数据帧的报头当中会包含两个字段,分别叫做源MAC地址和目的MAC地址
每一台计算机都至少配有一张网卡,而每一张网卡在出厂时就已经内置了一个48位的序列号,这个序列号被称之为"MAC地址",这个MAC地址是全球唯一的
在局域网中进行通信的时候,每一个主机在收到一个MAC数据帧后,都会提取该MAC数据帧的报头,找到对应的目的MAC地址与自己的MAC地址进行比对。若该MAC地址与自己的MAC地址不匹配,则直接将该MAC数据帧丢弃,只有MAC地址匹配时,该主机才会将该数据帧的有效载荷继续向上进行交付处理
扩展:
与碰撞相关的一种局域网攻击机制
若局域网内的某台主机一直向该局域网内发送一些无用的数据,那么其他主机一发数据就会产生碰撞,此时该局域网也就瘫痪了,这实际就是局域网本身的一个攻击原理。但需要注意的是,这台一直发送垃圾数据的主机,必须要通过某种方式绕过"碰撞避免"算法,否则当其发送的数据产生碰撞后,该主机自己也会执行“碰撞避免”算法
局域网之间都是通过路由器连接起来的,因此一个路由器至少能够横跨两个局域网。而这些被路由器级联的局域网都认为,该路由器就是本局域网内的一台主机,因此路由器可以和这些局域网内的任意一台主机进行直接通信
比如局域网1中的主机A想要和局域网2中的主机H进行通信,那么主机A可以先将数据发送给路由器,然后路由器再将数据转发给局域网2当中的主机H
采用不同通信标准的两个局域网内的主机通信
若路由器级联的两个局域网采用的是相同的通信标准,那么通信过程大致与上述一致。但被路由器级联的局域网可能采用的是不同的通信标准,比如局域网1采用的是以太网,而局域网2采用的却是令牌环网
由于以太网和令牌环网是不同的通信标准,给数据添加的报头也是不一样的,因此令牌环网中的主机无法对以太网当中的数据帧进行解包
这种情况实际是由路由器来处理的,路由器是工作在网络层的一个设备,可以认为路由器当中的协议栈是下面这样的
此时当数据要从局域网1发送到局域网2时,路由器收到局域网1的数据后,会先将以太网对应的报头进行解包,然后将剩下的数据向上交付给网络层,在网络层进行一系列数据分析后,再将数据向下交付给链路层,此时在链路层当中就会给该数据添加上令牌环对应的报头信息,然后再将该数据发送到局域网2当中,此时该数据就能够在令牌环网当中传输了
路由器为什么能够“认路”?
一个路由器可能会级联多个局域网,当路由器需要将一个局域网的数据转发到另一个局域网时,路由器如何知道该数据应该转发到哪一个局域网的呢?
路由器是通过IP地址来确定数据的转发方向的,公网上的每台计算机都有一个唯一的IP地址,而在数据向下进行封装时,在网络层封装的报头当中就会包含两个字段,分别是源IP地址和目的IP地址
当路由器需要将一个局域网的数据转发到另一个局域网时,在路由器的链路层会先将数据的在当前局域网对应的底层报头去掉,然后将剩下的数据向上交付给网络层,此时在网络层就可以获取到该数据对应的目的IP地址,然后路由器就可以根据该IP地址在路由表当中进行查找,最终就能够确认该数据应该发送到哪一个局域网
屏蔽底层的差异
IP地址的存在除了帮助数据"路由"以外,还可以屏蔽底层网络的差异。对于通信主机双方的IP层及其往上的协议来说,并不需要关心底层采用的是以太网还是令牌环网,只要填写了源IP地址和目的IP地址就能够将数据发送出去,因此现在主流的网络也被称为"IP网络"
这种类似的技术还有:
IP协议有两个版本:IPv4和IPv6。IPv4用32个bit位来标识IP地址,IPv6用128个bit位来标识IP地址
理解源IP地址和目的IP地址
因特网上的每台计算机都有一个唯一的IP地址,若一台主机上的数据要传输到另一台主机,那么对端主机的IP地址就应该作为该数据传输时的目的IP地址。但仅仅知道目的IP地址是不够的,当对端主机收到该数据后,对端主机还需要对该主机做出响应对,因此端主机也需要发送数据给该主机,此时对端主机就必须知道该主机的IP地址。因此一个传输的数据当中应该涵盖其源IP地址和目的IP地址,目的IP地址表明该数据传输的目的地,源IP地址作为对端主机响应时的目的IP地址
在数据进行传输之前,会先自顶向下贯穿网络协议栈完成数据的封装,其中在网络层封装的IP报头当中就涵盖了源IP地址和目的IP地址。而除了源IP地址和目的IP地址之外,还有源MAC地址和目的MAC地址的概念
大部分局域网都是以太网标准,其中 ether 对应就有"以太"的意思,而 ether 后面的这个地址就是当前云服务器所对应的MAC地址。但实际云服务器上的MAC地址可能不是真正的MAC地址,该MAC地址可能模拟出来的
理解源MAC地址和目的MAC地址
大部分数据的传输都是跨局域网的,数据在传输过程中经过若干个路由器,最终才能到达对端主机
源MAC地址和目的MAC地址是包含在链路层的报头当中的,而MAC地址实际只在当前局域网内有效,因此当数据跨网络到达另一个局域网时,其源MAC地址和目的MAC地址就需要发生变化,因此当数据达到路由器时,路由器会将该数据当中链路层的报头去掉,然后再重新封装一个报头,此时该数据的源MAC地址和目的MAC地址就发生了变化
在图中主机1向主机2发送数据的过程中,数据的源MAC地址和目的MAC地址的变化过程如下:
数据在传输的过程中是有两套地址: