文章目录
很高兴和大家见面,给生活加点impetus!!开启今天的编程之路
作者:٩( 'ω' )و260
我的专栏:Linux,C++进阶,C++初阶,数据结构初阶,题海探骊,c语言
欢迎点赞,关注!!
linux网络--基础概念
在上世纪,没有网络时,各个计算机都是独立的,如果需要进行多人协作,只能将数据手动拷贝下来,再去给另一台计算机上使用。但是这样效率大大降低。
随后社会发展,多人协作的场景越来越广泛,注定了网络的产生是必然的。
协议
先说结论,协议其实就是一种约定。
在现实生活中,你是否有以下的困惑?
自己组装电脑时,会发现不同厂商的零件最终是能够成功组装一台电脑并正常运行的,为什么呢?就是因为有协议的存在,约定了产品的规格,功能等等。
在计算机的发展过程中,计算机分为软件和硬件,软件如OS,硬件如cpu,磁盘等等。都是有自己的协议的。硬件部分的协议我不作考虑。主要是来讲解软件的协议。
先说结论:
软件级别协议是协议分层的。
在日常写代码中,其实我们也有分层的思想在。
如为什么不能让代码全在main函数内部,为什么要提供函数,其实都是在分层。

分层既然已经是一个既定事实,那么为什么要分层呢?
目的是让代码高聚合低耦合。方便对代码进行管理呀。
我们通过一个例子来引出协议;

当相隔千里的计算机与b需要进行协作时,如进行收发数据,会遇到哪些问题呢?
1:数据能够在相邻的设备之间进行传递
2:目标主机定位于路径选择
3:保证数据完好,不丢失
4:目标主机如何处理数据
为什么会产生这些问题?因为计算机之间的距离变远了,局域网根本无法满足远距离的要求。
注意:网络传递数据不是目的,而是一种手段。这样,数据就能够跨网络从一个计算机到另一个计算机了。
细看:其实我们能够发现这些问题也是具有层状结构的,肯定是满足了1,再来考虑2是否满足。如果说1都满足不了,2是肯定满足不了的。所以解决上面的问题肯定也是层状结构。
而为了解决这些问题,诞生了协议。那么协议肯定也一定是层状的。
理清逻辑:数据交互距离变远->产生了4个问题->衍生层状协议
OSI七层模型与TCP/IP五层模型

首先七层协议十分完备,但是5,6,7在OS上难以实现,现阶段我们主要提及5层的。七层后面讲

为什么叫做TCP/IP五层模型呢?我们主要研究软件,所以硬件不做考虑,而在剩下的四层中,最核心的就是网络层的IP, 传输层的TCP。
集线器:作用将衰弱的信号放大。只实现在物理层。有了集线器,相隔万里的电话就能够清晰听清楚对方的声音
交换机:局域网中数据帧转换工作。实现在物理层和链路层。
IP地址:与学号类似,能够快速定位目标主机,从而做出路径选择。
协议和协议与OS的关系
首先,操作系统各个厂商实现的都是各不相同的,linux,windows,macOS实现的各有千秋。但是为了保证远距离的信息传输,协议规定了五层模型的实现在不同系统上可以看做是相同的。

为什么这里叫做了协议栈,这点我们后面再说。
在协议栈中,最核心的是TCP/IP,因此也能叫做TCP/IP协议。
在其中,传输层和网络层由OS实现,虽然由操作系统实现,虽然不同平台操作系统不同,但是协议是相同的。而OS实现主要是c语言,所以:
结论:协议栈也是c语言写的,网络属于操作系统的一部分
说协议还是很抽象,具体到OS中,协议是由什么东西来标识的呢?
直接说结论:协议其实就是结构体!!
举个现实生活中的例子:网购了一个键盘,难道快递送到你手上时,是直接给你一个键盘吗?肯定不是呀,收到的肯定是键盘 + 快递单。上面记录着发货人地址及电话号码,收件人地址及电话号码。
为什么快递能送到你手上?因为你在快递单上写下了自己的地址及电话号码,能送到你手上的原因是你约定了送达的位置。即你在快递单上描述了你的位置属性信息。
此时快递单就是协议结构体初始化的对象!!
网络传输流程
局域网传输流程
局域网分为以太网和令牌环网。先以以太网为例。
mac地址:是唯一标识主机的唯一性, 48个bit位,6个字节 。
mac地址在网卡出厂时就由硬件固定了。即一张网卡,一个mac地址。
linux下查看mac地址:ifconfig
windows下查看mac地址:ipconfig /all

主机a发数据给主机e,连接同一个以太网的所有主机都能够受到该数据。但是会发现dist的mac地址与自身mac地址不同,此时就会将数据丢弃。
此时只影响到硬件到硬件层和链路层。因为驱动程序的存在,mac地址会被加载到链路层。
举一个例子:在一个教室里,老师叫张三,在教室里的所有同学其实都听见了,但不是叫他的名,肯定就不管了呗。
但是,当老师同时叫张三,李四和王五在讲话,赵六和田七在讲话...,此时教室里很吵,此时老师叫人就没用了。
对应到以太网,如果说主机a和主机b同时发信息。在同一个以太网中就会发生信息碰撞,肯能就会导致信息传输的稳定性。即以太网的本质是一个碰撞域。
当发生信息碰撞时,主机会a,b会执行碰撞避免算法,其实就是休眠上不同的时间。当主机a,b在休眠时,其他主机就有机会访问以太网了。
注意:上述过程有数据链路层自主完成的。
扩展:如果想黑一个以太网,也是可以做到的。利用某些工具,躲避碰撞避免算法。就能够保证每时每刻主机都在向以太网中塞入垃圾数据,导致其他主机在同一个以太网上一直休眠。注意注意:很刑。
示例:这也就是大学逃课时在寝室打游戏时网速很快,但是中午打游戏网速就很慢的原因了。因为数据碰撞次数大大提升了。
换个视角看待以太网:
如果将主机看作是一个一个的线程,那么以太网就是一个共享资源。由于碰撞避免算法,保证了只有一个线程在一个时刻访问临界资源。
令牌环网:在一个令牌环网上,哪个主机得到了特殊字段,谁就能够访问令牌环网(临界资源),那么此时令牌环网不是就锁嘛。
结论:局域网(以太网和令牌环网)的使用都要保证原子性
在上面我们提到主机a传输数据给主机b。那么为什么会让主机a传输数据给主机b呢?
因为用户层决定的。因为用户需要进行信息传输等目的,即在信息传输过程中。过程应该是从上到下,从下到上的贯穿。

而在上面我们也提到了。买键盘得到的其实是键盘 + 快递单。那么主机a给主机b传输数据时,不仅仅传输了数据。肯定还有类似快递单的协议结构体对象。而四层每层都有协议。即每层都会有一个类似快递单的协议结构体初始化的对象同数据一起传递给下层。

每向下一层,报文就会多一个报头。当目标主机接收到数据时,层层解包 + 分用(将去掉报头的报文传递给上层)。最多目标主机的用户就会得到不包含协议的信息了。
我们换个视角看。如果说是一个栈结果。封装和解包的过程不就是进栈和出栈嘛。

所以TCP/IP也被叫做协议栈呀,当然,协议栈有时也被叫做协议簇。即每层都有很多的协议。
例如:应用层有https,http,DNS等等,传输层有TCP,UDP等等,网络层有IP,ICMP,IGMP等等,链路层有ARP,RARP等等。
当用户进行数据交流时,逻辑上用户在直接进行数据交流。但是底层上看用户并没有面对面呀。就好比打电话。逻辑上两个人是在面对面说话,其中中间是隔着手机来说话的。而手机通过无线电才能够使得两个用户数据交流时能够跨距离。
同理:协议栈逻辑上用户层和用户层交流,网络层和网络层交流...
引出概念:
链路层和链路层交流的数据叫做数据帧,网络层,传输层,应用层同理。

接下来我们来说明一下封装和解包分用的过程:
封装:
前面提到过协议就是结构体。而每一层的报头其实就是结构体类型初始化的变量 。每一层都会添加自己层的协议报头。
在代码角度来说:因为报文需要被存储,肯定是需要缓冲区的。而封装的本质:封装报文头部,其实就是在不断拷贝结构体变量 。

因为每个结构体变量都有类型的,所以就能够得出index移动的位置。index += sizeof(a);类型的形式。
解包和分用:
过程为从报文中取出该层报头,同时将有效载荷传递给上层某个协议。
这里有两个问题:
1:报头和有效载荷分离的问题
2:有效载荷交付给上层哪个协议的问题
为什么会有这两个问题?因为如果报头和有效载荷分离的位置不对,传递给上层的有效载荷肯定是错误的。
先来解决问题1:
有些协议是固定长度的。从报文中取报头直接获取该长度个字节即可。这样就能够准确分离报头。如UDP等等。
有些协议自描述报头说明了该报头的长度是多长。如TCP等等
但是有些协议是变长长度的。但是想要获取报头的长度也是有办法的。这里我们后面对具体协议做说明的时候再来讲解。
解决问题2:
向下传递,即封装的时候,上层某个协议传递给下层某个协议时,在下层的报头中会有记录的。当向上传递时,取出来的报头中能够找到这个记录信息,明确说明了剩下的有效载荷传递给上层的哪个协议!!
跨网络传输流程
前面提到过IP地址类似学号,能够唯一标识一台主机。
IP地址分为IPv4和IPv6,前者占4个字节,后者占六个字节。
这里我们主要以IPv4来进行讲解,其中,可以使用 . 来分隔每个字节,形如:192.168.2.2
在前面我们提到过mac地址。mac地址也是在网卡中,生产出来就固定了。也是标识唯一主机的。那么IP地址和mac地址的区别是什么呢?
IP VS mac:
举例:放假回家,倘若是黑龙江到四川,那么路线肯定是先经过东北三省,随后经过中部,最后到达西南。在途中,相邻站点不断变化,即当哈尔滨->长春时,起始站为哈尔滨,目的地为长春,当长春->辽宁,起始站为哈尔滨,目的地为辽宁。当时在这个阶段中。你的起始地址永远是黑龙江,目的地永远是四川。因为黑龙江->四川永远不变。所以买票时一定是在该阶段中做路径规划的。即不可能再北上了吧?
对应到IP与mac。IP地址永远不变,而mac地址永远在变化!!
IP地址提供和长远目标,提供了路径选择的依据,而mac地址解决的是局域网转发的问题,即mac地址其实是局域网内有效的
再来说明跨网络传输:
一定会涉及到路由器。且因为是跨网络传输,则路由器肯定是有两个网卡的 。

路由器一个网卡连接局域网a, 一个网卡连接局域网b。
用户a传输数据给用户b。
网络层:报头会记录将源IP地址与目的IP地址,而链路层会记录源mac地址与目的mac地址。由于目的IP地址很明显不可能是局域网a的,所以一定涉及跨网络传输,且此时该数据一定会发给路由器。此时连接局域网a的所有主机能够接收到信息,但是经过驱动程序(链路层)发现不是发给自己的。则直接丢弃。
而在路由器视角,发现信息时发给自己的。就会解包和分用,而在路由器的网络层能够拿到目的IP地址。发现与路由器另一个网卡的IP地址类似。此时就会再次封装并将数据传输给另一个网卡,即局域网b。对比目的mac地址与目的IP地址,最终由主机b解包和分用拿到数据。
这只是一个大体过程。具体的细节还需要后面的慢慢雕琢。
通过上面过程能够得出结论:
1:路由器至少工作在网络层,能够将一个数据从一个网传输到另一个网。因为路由器至少都需要拿到IP地址吧
2:IP地址统一了互联网的通信标准。
为什么这样讲?首先网络是由硬件和完成的,即网卡。其次在网络发展初期,各种实验室都在发展网络。但是由于缺少标准,单靠硬件是无法进行数据传输的。如果此时再来指定标准,淘汰一些方式,注定导致许多工程师失业,即如果不指定标准,其实阻碍了网络的发展。在此基础上,添加了软件层来解决问题。单看网络层。网络层得到的报文都是一样的。但是在链路层和硬件层,基本都是不相同的。
为何IP地址统一了互联网的通信标准,下图我直接使用数字的形式代表了报文:
网络层得到的报文都是一样的,链路层和硬件层,不相同!!

通过上面这个过程,其实也不难发现,mac地址确实只是在局域网中唯一标识主机,而并非全球
在上面我们提到的都是主机与主机之间的交流,那么是谁让主机与主机交流的?自己没事在那里玩?
都是用户再让主机进行交流,那么用户是以什么形式呢?进程。
当用户访问app,点开时就变成了进程。用户通过进行访问服务器无非就两种情况:拉取服务器上的数据到本地, 向服务器上传数据。
当用户拉取数据到本地,那么数据是怎么能够精准到目标进行去的呢?
即前面我们都在谈论主机与主机之间的数据传输,这不是目的,只是一种手段,真正的目的是数据发送给进程,供用户访问。
所以想要数据准确传输到进程中,即一定需要有唯一标识进程唯一性的东西。因为需要找到这个进程嘛,这样数据才能传过去嘛

如图:服务器永不关闭,所以qq在服务器上运行时,肯定也是进程了。而客户端运行起来的qq肯定也是进程。客户端qq和服务端qq进行数据传输。这不就是进程间通信嘛。
结论:网络通信本质:不同主机上进程间通信
在系统部分讲的进程间通信,是在本地完成的,借助的是systemV标准,但随着网络发展,本地通信其实不怎么使用了。而网络主要使用POSIX了。
对于网络下的进程间通信,有两个视角:从冯诺依曼角度来说,从网卡获取数据,由于网卡是外设,访问外设即IO,从文件系统来看,网络/网卡是文件,访问文件肯定需要从磁盘加载到内存,同样也是与外设打交道,所以同样也是IO。
端口号port
端口号是2字节16bit位的整数。
端口号是传输层协议的内容。
端口号能够唯一标识一个进程。
问题:pid VS 端口号port
既然进程中有唯一标识进程唯一性的pid,那为什么还需要端口号呢?
换个视角,如果网络部分和系统一样,都是用pid,会造成什么后果呢?
理由1:耦合度高,pid被影响,即系统受影响,会造成网络也会受到影响。
理由2:每个进程都有pid,但不是所有进程都要进行网络通信。否则无法标识该进程是否进行网络通信。即端口号是进程是否要网络通信的强标识
生活中很简单的例子:大学生有身份证,那为什么还要有学号呢?上班族有身份证,为什么还要有工号?
问题:IP VS 端口号port
IP是标识主机唯一的,而端口号是标识进程唯一的。而一个IP中可能有多个端口号
举个生活中的例子:某一个公司(IP)和公司中的员工(端口号)
结论:IP + 端口号port = 标识互联网中唯一一个进程
以服务端和客户端为例:

数据传递的报文信息中包含src_port和dist_port。通过dist_port,能够找到服务端的目标进程。如果是拉取数据,同样的方式,也能找到客户端的进程。
先来讲细节:
1:服务器永不关闭,所以进程在服务端上,即服务器上的port是不会改变的。而客户端进程port是能够改变的。
为什么呢?如果服务器上的目标进程port改变,造成客户端是一定访问不到的,客户端port可以改变,那么服务端就能找到吗?确实,用户打开app,变成进程,即在服务端会显示请求登录等信息。此时服务端就能够拿到port。
2:网卡数据接收是异步的。首先,OS怎么知道网卡上有数据?类似于OS怎么直到键盘上有数据按下?都是中断,而终端类似信号,都是异步的。
3:网络通信都需要访问服务端吗?
都是需要的。
难道客户端与客户端的相互访问都需要经过服务端吗?需要,服务端拿到两个客户端的端口号,需要做交换。否则端口号都不知道,对应进程都找不到是谁
扩展两个问题:对于端口号
1:OS是如何找到一个进程的?
2:找到进程,如何把网络数据,交给这个进程
先来解决问题1:
首先底层使用的是哈希表,键值映射关系为<port, PCB>,通过port,能够找到该进程的pcb。
解决问题2:
首先下层传递个OS(网络层和传输层)的报文随时随地都会产生,有些是刚刚收到的,有的是马上处理的。OS需要对其进行管理,先描述再组织。而报文是使用缓冲区存储的,描述结构体中一定有指针指向该缓冲区。
通过port,能够找到pcb,而pcb有struct file指针,struct file中有指向缓冲区的指针。而存储报文的缓冲区的内容直接拷贝过去即可。那么我们该如何找到存储报文内容的缓冲区?即找到报文描述结构体呢?
linux下一切皆文件,网卡也是文件,直接通过fd就能够找到网卡中的数据了。
梳理上文的所有思路:
距离变长->产生4个问题->引出层状协议(TCP/IP协议)->协议与OS关系->协议的本质->网络传输流程(局域网,跨网络)->局域网通信/封装,解包和分用解决两个问题->跨网络通信 ->人(进程在跨网络通信中的作用)->端口号(进程间通信,区别pid,ip)
