
🔥海棠蚀omo:个人主页
❄️个人专栏:《初识数据结构》,《C++:从入门到实践》,《Linux:从零基础到实践》,《Linux网络:从不懂到不会》
✨追光的人,终会光芒万丈
博主简介:

目录
前言:
作为一名开发者,我们每天都在与网络打交道,但你是否好奇过,当数据穿梭在 Linux 系统中时,那里究竟发生着什么?
今天这篇文章不打算用枯燥的公式和代码来轰炸你。相反,我想邀请你放下畏难情绪,随我一起推开那扇看似厚重的大门,以最直观的视角,去初次感受 Linux 网络这颗"心脏"的跳动规律。让我们从宏观出发,先看清这片波澜壮阔的连接图景。
一.计算机网络背景
在现实世界中,我们人之间是需要协作的,而我们同样也需要使用计算机来完成工作,我们人直接可以直接面对面来进行通信,交流,合作来完成一些工作。
但是计算机呢?计算机是人的工具,人之间既然需要协作,那么计算机之间也要协作,那么计算机之间又该如何进行协作呢?
答案当然就是我们今天的主题:网络。在计算机的发展历程中,从它的诞生,再到操作系统,最后到计算机网络技术,这些技术的诞生都是源于人们日益增长的需求而出现的,所以:这个世界产生计算机网络技术,是必然的结果!!!
那么下面我们来简单了解一下网络的发展过程:

那么最开始呢,每个计算机之间相互独立,每个计算机中都存储着不同的数据,在这个阶段我们想要实现计算机之间的协同工作,需要用到类似:软盘等硬件,将这种硬件插入到不同的电脑中,借此来完成数据的共享,但是这种方式显然太麻烦了。

后来就有了最初的网络,多个计算机中的数据可以通过网络上传到服务器中,不必再靠硬件来实现计算机之间数据的共享,方便了许多。

再到后来计算机的数量更多了,此时又出现了新的设备:交换机和路由器,这些计算机通过这些设备来完成协作,这种方式我们就叫做:局域网LAN。此时的技术就已经能支持不同地区的计算机之间的通信了。

最后将多个局域网合并在一起就形成我们今天的:广域网WAN,它所覆盖的范围就更广泛了,甚至可以跨越国家。
二.初识协议
"协议"简单理解就是一种约定,什么意思呢?

以上图为例子,我们知道计算机之间的传输介质是光信号和电信号,通过"频率"和"强弱"来标识0和1这样的信息,那么此时产生的问题就是:你的计算机将信息传给另一个计算机,它怎么知道你传的信息是什么意思呢?
所以这之间要有一个约定,比如我传1010是什么意思,1111是什么意思等等,我们之间要约定好,也就是需要约定好双方的数据格式,这个约定我们就叫做:协议。
但是此时又有一个问题:能够通信的两台计算机,只约定好协议就可以了吗?
就比如上面,我们只约定好我们传递的信息只能是0和1,但是你用频率表示01,我用强弱来表示01,就好比我用中国话,你用英语,虽然大家遵守的是一套通信规则,但是只是定好了基本的协议,也是无法正常通信的。
所以一份完善的协议,需要我们去制定更多更细致的规则,并让参与的人都要遵守,就比如:
1.计算机生产厂商有很多
2.计算机操作系统也有很多
3.计算机网络硬件设备同样有很多
所以为了让这些不同厂商生产的计算机能够互相通信,就需要约定一个共同的标准,大家都要遵守,这就是:网络协议。
但是网络协议也不是什么人都能够来制定的,一般是具有定制协议或者标准的资格的组织或者公司或者具有江湖规则的组织或者公司。
就比如在5G领域,华为就有资格来制定网络协议,它在这个领域是具有很大的话语权的,对应的就是上面的公司。
三.协议分层
3.1软件分层的好处
协议本质也是软件,在设计上为了更好地进行模块化,解耦合,也是被设计成为层状结构的。
这在我们日常写的代码中其实也能够体现分层的思想,就比如我们写的基类和子类,基类就是一层,而子类又是一层,我们要想让基类的某个函数实现不同的功能,只需要修改子类即可,不需要修改基类。
而对于软件分层的好处,下面我们通过一个简单的例子来去理解:

我们日常在打电话时,在语言层面我们都是用汉语在沟通,但是在通信设备层即电话机,它们可不是用汉语来进行沟通的,它们有自己的协议,通过遵守协议的内容,他们就能知道对面的电话机传来的信息是什么意思,进而对它进行解码,转化为我们能听懂的汉语。
在上面的例子中,我们的"协议"只有两层:语言层,通信设备层。可以很明显的看到,不同的层级,区别还是很大的。
而我们即便在通信设备层和语言层进行变更,只要遵守相应的协议,并不会影响我们的通信,这里我们就能很明确地感受到分层可以实现解耦合,让软件维护的成本更低。
3.2OSI七层模型
OSI(Open System Interconnection,开放系统互连)七层网络模型成为开放式系统互联参考模型,是一个逻辑上的定义和规范。


这就是OSI七层模型的各个层级的名称及功能简介,但是站在网络的角度,OSI定的协议七层模型其实非常完善,但是在实际操作中,会话层,表示层是不可能接入到操作系统的,所以在工程实践中,最终落地的是五层协议。
对于上面的各个层级,我们现在还理解不了,之后通过后面的学习,我们才能慢慢了解,目前我们简单了解一下即可。
3.3TCP/IP五层(或四层)模型
既然最终只能落地五层协议,那么就有了现在的TCP/IP五层模型,TCP/IP是一组协议的代名词,它还包括许多协议,组成了TCP/IP协议簇。

上面就是TCP/IP分层模型的示意图,它将应用层,表示层和会话层合并为应用层,对于TCP/IP分层模型我们现在对于它的每个层级也不理解,所以这里我们同样了解一下即可。
四.再识协议
4.1为什么要有TCP/IP协议?
我们要知道,其实,在没有网络的时候,即便是在单机的情况下,计算机内部也会有自己的协议,就比如:即使没有网络,我们插上U盘,电脑也是能够识别我们的U盘的,这就与电脑中的USB协议有关。
但是这个时候的计算机网络的内部通信的距离也只是局限在计算机的内部走线,距离也就只有几米甚至更短,而我们现在的网络通信,距离可是以公里为单位,短则几公里,长则几千公里,那么距离变长就必然会引发新的问题,我们下面来看:

就比如上面的主机A要向主机C发发送信息,那么因为距离变长了,就需要考虑上面的几个问题:
1.我要发送数据给主机C,得先发送到路由器R,怎么发?
2.网上这么多主机,怎么定位并找到主机C呢?
3.如果我的数据发出去,中途丢失了怎么办?
4.我们发送数据并不是目的,目的是让接收数据的另一台主机知道怎么处理这部分数据,怎么去使用,所以该怎么办?
从上面的几个问题中我们就可以看发现,这几个问题本身就是具有层次性的,它们所涉及的知识点不止是一方面,所以有了新的问题就要有新的解决问题的方案。
而TCP/IP协议就是一种解决网络通信的具体解决方案,而TCP/IP协议就是参考OSI七层模型而设计出来的,OSI七层模型就相当于一个模板,所以根据这个模板而设计出来的解决网络通信的具体解决方案并不只有TCP/IP协议这一种,还有其他的解决方案。
4.2TCP/IP协议与操作系统的关系

我们可以通过这张图来观察两者之间的关系。
TCP/IP协议的这五层模型我们通常将其称为:网络协议栈,既然我们要实现网络相关的技术,就要根据这五层模型在我们的计算机中进行实现,不同的模型对应着电脑中不同的部分。
就比如:网卡这种硬件肯定要在底层硬件这部分进行实现,应用层是面向用户的所以肯定要在最上层进行实现。
而这种对应关系是每一个操作系统都要遵守的标准,不仅仅是对应关系,里面每种协议栈都要根据标准来进行实现。所以此时我们就能理解为什么不同的操作系统之间是能够进行通信的了,正是因为上面的原因,而这也是互联网的基础!!!
在上面的计算机结构图中我们讲过,操作系统之所以在中间,就是因为它起着承上启下的作用,在这里面它就是核心,那么对应的在操作系统中实现的传输层和网络层自然也就是网络协议栈中最核心的部分了。
而传输层中最著名的协议就是TCP,网络层中最著名的协议就是IP协议,既然TCP和IP是核心,那么我们将这个协议整体称为TCP/IP协议不过分吧。
所以回到我们的标题,TCP/IP协议和操作系统之间是什么关系呢?
既然TCP/IP协议的核心都是在操作系统中进行实现的,所以我们可以认为TCP/IP协议就是操作系统的一部分。
4.3究竟什么是协议?
在上面我们说协议就是一个"约定",但毕竟这种说法还是太笼统了,而要弄清楚到底什么是协议这个问题的答案,我们就要达成两个共识,前面是第一个共识,下面我们还要达成一个共识:
一个问题:OS系统一般是用什么语言来写的呢?
答案很明显,是用C语言写的,而这就是我们要达成的第二个共识。
而有了上面的两个共识之后我们再来思考一个问题:协议可不只有我们上面介绍的TCP/IP这两种的,是有很多种的,那么OS要不要管理这些协议呢?
当然要管理,那么依旧是先描述再组织,对于如何组织我们暂且不谈,那么OS系统是如何描述这些协议的呢?
我们要知道,协议中是有很多属性的,比如:状态信息,地址信息,要发送的网络数据等等,这些属性是不同类型的,所以该如何整合这些属性呢?
没错,因为OS系统是由C语言实现的,所以我们就用结构体来描述协议,结构体中就可以存储不同类型的属性。

那么下面我们就可以来看这张图了,在网络协议栈的每一层都会存在这样的结构体,而我们上面也说了不同的操作系统对于协议的实现是相同的,所以即使是不同的操作系统每一层之间也是能够相互识别各自层级的结构体的,并从中提取相应的信息。
这里就是对上面不同的操作系统之间也能够进行网络通信更加具体的说明,也让我们对于协议有了更深刻的认识。
五.网络传输基本流程
5.1局域网通信原理
我们首先来思考一个问题:两台主机在同一个局域网中,那么它们两个之间是否能够直接进行通信呢?
答案当然是可以的,这其实就类似于我们上课的情景,我们来看:
在一间教室中,除了老师,还有其他的学生,那么此时如果老师提问某一个学生,那个学生听到老师喊他的名字,所以他就站起来回答问题了。
那么在上面的情境中,我们来思考一个问题:主机是怎么知道发送数据时发给自己的?怎么知道不是发给自己的?
在上面的情境中我们知道学生知道老师喊他是他听到了自己的名字,那么对应的我们的主机也应该有自己的" 名字 ",那么这个名字是什么呢?
答案就是MAC地址,下面我们来看关于MAC地址的相关介绍:
1.MAC地址⽤来识别数据链路层中相连的节点;
2.⻓度为 48 ⽐特位, 即 6 个字节。⼀般⽤ 16 进制数字加上冒号的形式来表⽰(例如:
08:00:27:03:fb:19)
3.在⽹卡出⼚时就确定了, 不能修改。mac地址通常是唯⼀的(虚拟机中的mac地址不是真实的mac地址, 可能会冲突; 也有些⽹卡⽀持⽤⼾配置mac地址)
那么下面我们就来看这张图:

就比如此时主机A要向主机E发送消息,那么它所发出的信息中就包含了目的地址,这个目的地址就是主机E的MAC地址,所以主机E就知道这条信息是发给自己的。
并且我们从上图中也可以看到,不只是主机E能够收到主机A发出的信息,其他的主机也是能够收到信息的,并从信息中判断出这不是发给自己的,这并不难理解,在上面教室的例子中,老师提问某个学生,其他的学生也是能听到的,并且知道老师喊得不是自己,因为喊得不是自己的" 名字 "。
那么解决了上面问题后,我们再来思考一个问题:一个课堂中只有老师会说话吗?或者说只有一台主机会向其他的主机发出消息吗?
答案肯定是不会的,所以在这个局域网中就会存在大量的信息,那么不同的信息会互相干扰吗?
当然会,就像老师上课过程中还要整顿纪律,就是因为下面学生的窃窃私语影响到老师向其他人发送信息了,那么该如何解决这种问题呢?

答案就是在局域网中,也就是以太网中,每台主机会有一个机制,叫做:碰撞检测和碰撞避免。
碰撞检测的作用是当一个主机想要发送消息时,它会检测当前的以太网中是否有其他的信息正在发送。
而碰撞避免就是当经过碰撞检测后发现当前的以太网中有信息正在发送那么当前的主机会进行等待,直到以太网中没有信息发送,这种做法就避免了消息之间发生碰撞。
而我们可以认为以太网就是一个碰撞域,是一个基于碰撞检测和碰撞避免的通信模式,这种模式也是应用最广泛的通信局域网协议。
而我们可以用另一种角度来理解这个模式,在这个以太网中,不只有一台主机可以发送消息,其他主机也可以在这个以太网中发送消息,所以这个以太网我们是不是可以认为它就是一种共享资源呢?
那么碰撞检测和碰撞避免这种机制保证了任何时刻,只允许一台主机使用以太网,向目标主机发送数据,而这部就相当于我们之前讲的" 锁 "的功能吗?
而有了" 锁 "之后我们访问以太网这个共享资源不就相当于临界区式的访问吗?
通过上面另一种角度对于该模式的分析,相信我们对其有了更深刻的认识。
5.2两台主机发送消息的过程
那么有了对上面局域网通信原理的初步认识,下面我们具体来看一看两台主机的整个通信过程。

由左边的用户A向右边的用户B发送消息,按照网络协议栈的顺序从上到下一层一层地进行传递。
而用户B要想接收到信息,顺序和用户A正好是相反的,它要从最底层的硬件接收到信息,一层一层地向上传递,最终将信息呈现给用户B。
那么知道了传递信息的大概流程,那么我们来思考一下:里面每一层之间是如何传递消息的呢?

因为每一层都有相应的协议,所以当我们进行上述的传输流程的时候,要进行封装和解包,左边发送消息的主机要对消息进行封装,右边接收消息的主机则要对信息进行解包。
可能有人会觉得:为什么要进行封装和解包呢?
我们可以用快递的例子来理解,你买了一件物品,比如:洗面奶,那么你收到的就是洗面奶的本体吗?
并不是吧,洗面奶外面有厂家的包装盒,包装和外面可能还会有泡沫板,泡沫板外面还有快递的包装盒,我们拿到的商品是进行了封装的,并且我们会其还会对其进行解包,也就是拆快递。
只有这些还是不够的,我们是怎么知道这是我的快递的呢?
是不是根据快递外面的快递单啊,快递单上有我们的手机号,地址,姓名等信息,所以我们要对信息进行封装,添加一些必要的信息,比如:地址信息,协议标识等。
通过上面的例子我们就对封装和解包有了一个初步的认识,那么下面我们就来看看这些层级之间是如何进行封装和解包的:

每一层进行封装的东西我们称为:报头,而被封装的内容我们称为:有效载荷。
拿应用层来举例,对于这一层而言,用户A要发送的" 你好 "就是有效载荷,而应用层就会在其外部封装一层报头。
而对于它下面的传输层而言,上面传下来的应用层报头+" 你好 "就是有效载荷,而它要在其外部封装一层报头。
那么这个报头到底是个什么东西呢?
经过我们上面的讲解我们已经知道了协议本质就是一个结构体,所以通过协议传递出里的东西是什么呢?
是不是就是一个结构体对象啊,里面有着各种不同的属性。
经过上面封装的过程后,最终右边的主机拿到的就是被封装了很多层的信息,而它会从下往上进行解包,正是因为左边的主机是从上向下进行封装的,所以右边的主机从下往上进行解包时每一层对应的都是最外面的那层包装。
而网路协议栈的每一层的实现都是相同的,相应的层级是能够识别对方的报头的,也就能对其进行解包。
就这样一层一层的解包,和我们一层一层拆快递是一样的,最终就会在用户B面前呈现用户A发送的消息。
而我们将处于数据链路层的信息称为:数据帧,处于网络层的信息称为:数据报,处于传输层的信息称为:数据段。
那么通过上面的讲解我们对于封装和解包有了更深入的认识,那么下面我们再补充一些细节。
细节一:

我们不妨将封装和解包的过程竖着来看,左边是封装的顺序,而右边则是解包的过程,我们是否感觉这个顺序很熟悉呢?
没错,这种后进先出的特性不正是栈吗?
所以为什么我们上面一直在说网络协议栈啊,这个栈就体现在这里,它封装和解包的过程正体现了栈的特性。
细节二:
任何协议(应用层除外)都要解决两个问题:
1.将报头和有效载荷进行分离
2.把数据交给上层哪一种协议的问题
对于第一种问题我们上面已经讲过了,而对于第二种问题我们要知道每一层的协议可不止有一种,就拿网络层举例,不止有ip协议,还有:icmp,igmp,arp,rap等协议。
所以每一层不止要完成将报头和有效载荷分离的工作,还要知道将数据应该交给哪一种协议,而这个过程就叫做:分用。
所以我们在上面的图中在右边的主机上写的是解包和分用的过程,那么分用是怎么完成的呢?
答案就是在左边主机进行封装的时候会预留一个" 指路牌 ",叫做:分用标识符,右边主机的每一层都会根据这个分用标识符来确定要将数据交给上层的哪一个协议。

对于分用的过程我们可以看上面这张图。
5.3跨网络传输
上面我们针对局域网通信进行了讲解,那么网络不止有局域网,还有广域网,也就是跨网络进行传输。

而我们要想做到跨网络传输,就要用要路由器这种设备,准确来说我们要用到ip地址,那么ip地址又是什么呢?
IP协议目前有两个版本,IPv4和IPv6,对于这二者我们目前只讲解IPv4。
1.IP 地址是在 IP 协议中, ⽤来标识⽹络中不同主机的地址
2.对于 IPv4 来说, IP 地址是⼀个 4 字节, 32 位的整数
3.我们通常也使⽤ "点分⼗进制" 的字符串表⽰ IP 地址, 例如 192.168.0.1。⽤点分割的每⼀个数字表⽰⼀个字节, 范围是 0 - 255。
在上面局域网中我们介绍了MAC地址,那么MAC地址和IP地址之间有什么区别呢?下面用一个例子来说明:

这里用我们很熟悉的西游记来举例,假设现在唐僧四人要去西天取经,这一路上要经过上面所示的三个地方,分别是:车迟国,女儿国和黑风岭,而他们每到一个地方那里的妖怪都会问他们:" 你们从哪里来?要到哪里去啊? "
唐僧此时就会说:" 我们自东土大唐而来,到西天去求取真经 ",而妖怪此时又会问:" 那你们上一站是从哪儿来的啊? "
如果是在车迟国,那么唐僧会说:" 我们从长安来 ",然后唐僧就会问妖怪:" 那我们下一站要去往哪里呢? "
此时妖怪就会说:" 那你们下一站要去女儿国 ",而到了女儿国后也同样会问上面的问题,但是对于从哪里来和到哪里去这两个问题的回答始终如一,但是对于上一站从哪里来和下一站到哪里去答案却不再一样了。

而对于一直不变的从哪里来和到哪里去分别对应的就是源IP地址和目标IP地址,而始终在变化的上一站从哪里来和下一站到哪里去分别对应的就是源mac地址和目标mac地址。
在这整个过程中,IP地址始终不变,mac地址始终在变化,也就是根据目的IP地址,会动态选择出我要经历的mac地址,也就是我要经历哪些主机或者路由器。
那么下面我们就来看一看这个过程:

这里以经过一个路由器为例,当上层的数据交给网络层后,网络层会根据目的地址判断是否是当前局域网中的地址,那么是如何判断的呢?
我们要知道一般在一个局域网中的地址都属于一个网段,就如上图所示,在左边局域网中的主机他们的地址都很相似,只有最后一部分不同,而上面我们的目的IP地址明显就和这个局域网中的地址不一样,所以网络层就判断出目的IP不属于当前的局域网。
而判断出结果后网络层会将地址交给路由器,但是网络层能直接地址交给路由器吗?
当然不能,网络层照样还得将信息封装交给数据链路层,再由数据链路层交给路由器,那么路由器既然要接收数据链路层的信息,在其里面自然也会有数据链路层和网络层。
下面我们来看更为完整的过程:

可以看到,在将信息发送给路由器前后,源IP地址和目标IP地址始终没有发生变化,而源MAC地址和目标MAC地址在路由器前后发生了变化:

这还只是一个路由器,在实际传输的过程中是要经过很多的路由器的,而每经历一个路由器,就要进行向上交付,解包,向下交付,封装的过程,mac地址也会随之发生改变,因为mac地址只在局域网有效!!!

最后我们来看一下多个路由器的流程图,加深我们对于这整个流程的认识。
以上就是万物互联的起点:走进 Linux 网络的心脏,开启一场从零开始的底层探索之旅的全部内容。