文章目录
- 基本认知
- 数据跨网络传输
- 初识ip地址
- 端口号
- 端口号的理解
- 进程与端口号
- 总结
本篇是基于前面对于网络的基本框架搭建,进而进行相关概念的进一步理解,为后续准备
基本认知
那么首先总结一下一些基本的相关结论性的信息
- 对于任何协议来说,它本身都应该拥有把报头和有效载荷进行分离的能力,这是在前面的基础认知中已经有的一个概念,也正是因为有这样的结论,才能做到把数据不断的进行封装传递到另外一个网卡,再不断向上解压缩的过程,这样的结论使得每一层协议实际上看到的内容是一样的,这也是所有操作系统都必须遵循的一个原则
- 在局域网中,两台主机之间是可以直接进行通信的,那局域网通信的原理就是,每一台主机都有一个属于自己的专属48位的Mac地址,那这个Mac地址本身就是来标记当前主机在局域网的信息,所以在一个局域网中,一个主机想向另外一个目标主机发送一条信息的时候,就必须要面临的问题是,谁发,给谁发的问题,因此就会有根据报头检测,进而对于有效载荷进行分离,把对应的Mac地址进行比对,如果是给自己发的信息就进行保留,如果不是给自己发的信息就进行丢弃,这样就能有效的找到属于自己的包,那这带来的一个结论也是显而易见的,在一个局域网通信的时候,实际上这个包在传递的过程中是所有的主机都是有看到信息的权利的,至于想不想接受是一回事,但是都是可以看到的,所以进而又引出了对于碰撞域的概念理解
那有了上面的结论,那下面来进入下面的话题,叫做数据的跨网络传输
数据跨网络传输
现在有这样的场景,有一份数据要从主机A传递到主机B,那如果这两个主机是处于同一个网络自然直接传递即可,但是如果跨网络,就需要借助路由器这样的设备,路由器设备的工作效果就是可以连通左侧和右侧的两个子网,进而进行两个子网之间的设备来进行通信,具体的效果如下所示
在上图中出现了陌生的概念,令牌环网,那首先介绍一下这个概念
对于令牌环网来说,它的一个特点是,在任何时刻只允许在局域网中有一台主机,保证的原理就是借助一个特定的标识数字,当有一个主机拿到了这个标识数字,那么就可以进行通信,但是如果没有拿到这个数字就不能进行通信,这和以太网的处理原理是不一样的,以太网对于数据冲突的解决方式是借助了一些算法,来进行碰撞检测和对应的碰撞处理
那这个令牌环网的逻辑其实和前面锁的概念是很像的,都是用一个特定的数据来进行表示持有,而在这个令牌环网的概念中,可能具体的实现措施是借助了这样的一个类似于锁的概念来实现的,这个概念其实并未特别广泛的使用,这里想要表达的意思是,令牌环网和以太网的这个驱动程序,它们都是隶属于数据链路层,只不过是底层的协议可能不太一样,以太网有以太网的协议,对应的令牌环网也有,但是不可否认的是,这并不重要,因为网络已经实现了分层解耦的概念,这意味着从底层的角度出发,把这两个网进行对应的替换并不会影响整体网络的情况,网络是一个层状的结构
那这里想要输出的观点是,如果想要把数据从一个网络交给另外一个网络,那我当前的主机是如何知道这件事的呢?因此就引入了本篇要介绍的第一个概念:ip地址
初识ip地址
什么是ip地址
现在对于ip地址进行一个初步的认知,未来会有更加详细的解释
从一个非专业的角度来讲,ip地址通俗来说就是能够保证一个主机在全网的唯一性,这样的描述可能未必正确,但是在绝大多数的情况下是成立的,而ip地址和Mac地址是两个什么概念呢?简单来说,ip地址可以保证的是全网的唯一性,而Mac地址只是运用在局域网中,在局域网中可以保证自己的特定性
ip地址是分为共有ip和私有ip的,那对于公网ip实际上是见到很多次的,例如在Linux的云服务器上就使用过公网ip的概念,那不管怎么说,ip地址都是凸显一个唯一性,而Mac地址会随着所处的局域网的改变而发生改变
主流的ip地址
在现在社会,主流的ip地址是ipv4,简单来说就是这个ip地址占用的是四个字节,例如有这种形如192.168.1.1这样的,就叫做是ipv4的ip地址,公网ip能够标识互联网中特定主机的位置,在未来进行传输的过程中,就可以借助这个ip地址在特定的路径中进行转发,进而实现从一个主机到另外一个主机这样的一个过程
那借助路由器可以实现信息的传递,那具体是如何实现的?我们通过下面的这个图来进行解释
那从上面的图示信息中我们可以看出的一个基本的结论是,对于这个路由器来说,它既可以识别以太网的信息,也可以识别令牌环网的信息,它拥有可以把旧的报头丢掉,新的报头装上去的功能,再不断地进行新的传递和识别,因此我们说,作为底层的局域网对于网络层来说重要吗?其实并不重要,因为在ip协议往上看,都无所谓,底层已经被封装的严严实实,只需要看ip协议网上看即可,因此引出这里的下一个结论:
ip协议屏蔽了底层网络的差异化,靠的就是工作在ip层的路由器
ip实现了全球主机的软件虚拟层,一切皆是ip报文
于是如果有两个非常远距离的信息,它们是如何进行传递的呢?
如上图所示,借助所处在网络层的路由器,就可以实现远距离传输,当然这中间必然有很多的细节,未来会对这些细节进行一一阐述
端口号
下面介绍的下一组概念叫做端口号
当一些数据想要进行网络通信的时候,必然首先要把对应的进程运行起来,才能谈网络通信的概念,而真正通信的概念,也必然是要有用户来进行发起的,一个基本的逻辑是可以通过ip地址,来把数据从a主机运送到b主机去
在网络协议中,有四层协议,分别是数据链路层,网络层,传输层和应用层,那其中传输层和网络层是在操作系统内部实现的,而在通过网络实现通信的时候,本质上是进程a向进程b发送对应的数据请求,只不过是进程a和进程b是使用了对应的系统调用来完成的通信过程,而在平时的日常app中,绝大多数的情况都是在远程有一个云服务器,它会提供一个服务端,那在未来用户的手机上会有一个用户端,服务端和用户端进行相互交互,就能实现一个交换数据的过程,所以网络通信的本质,就是进程间通信
那谈及进程间通信,就又要谈及的话题是,进程间通信的本质,就是让两个不相关的进程看到同一份资源,进而才能进行进程间通信,那么在网络通信的本质,就可以理解为是网络协议栈利用网络的资源,来使得让不同的进程看到了同一份资源,一个从网络内写,一个从网络里面读,就能拿到最终想要的数据
在前面的理论基础中对于报文,报头,有效载荷有一个基本的认识,那么这如何与端口号建立联系呢?其实,每一层协议想要解决的问题就是把自己的有效载荷交给上层协议,在这当中,例如在应用层当中有各种各样的应用层协议,那在底层的操作系统中只是收到了一个报文,那操作系统应该进行怎么操作封装,来最终把这些信息传递给哪一个具体的应用呢?于是就有了端口号的概念,这要求上层和传输层之间必须约定好一个具体的方案,而这个方案就能够实现的效果是,把数据准确的从传输层传递给上层,那这个标识其实就是端口号
端口号是会存储在对应的传输层协议中的,现在这里只是对于这个过程有一个比较基础的认识,如果现在想要实现一个基本的代码,那么首先要做到的一点就是,想办法让服务器的应用层绑定一个端口号,一旦绑定了这个端口号,那么在传递的过程中在报文中就要带上和端口有关的信息,在未来传递到应用层后,就会进行对应的解析,提取出端口号,把有效载荷给到对应的端口号即可
那这个端口号,对于客户端和服务端来讲,都能成为一个唯一的标识,作为标识该主机上的某一个特定的进程,所以在网络中可以理解到,进程可能有10个8个或者更多,但是网络协议栈只有一套,每一个协议栈都是一个公共的资源,在收到对应的信息后,都能把信息转交给另外一个特定的进程,所以就必须有一个端口号来做对应的识别,这样传输层就能把数据传递给一个指定的进程了
端口号的理解
对于端口号来说,先从代码的角度来认识,端口号其实就是传输层协议的一个内容,那这个内容通常来说是一个两字节的正数,端口号通常用来表示一个进程,那么就会告诉操作系统来说,底层收到了哪一个具体的数据,最后要保证把对应的数据交给对应绑定的特定端口号的进程,这是一个基本的认知
根据前面的内容来看,对于ip地址的理解要理解到,ip地址可以标识唯一的一台主机,那这台主机的端口号又能标识唯一的一个进程,这就意味着一个端口号只能被一个进程所绑定,端口号的英文一般叫做是port,那就意味着这个端口号会成为主机上的一个进程的标识,这也就意味着,借助一个ip地址和一个端口号,就能立刻定位到全网的一个唯一的进程,这样就能做到精确的访问
客户端认为,只要有一个ip地址和一个端口号,就能成为互联网的唯一一个进程,那如果服务端也是这样,那么就能实现全网中两个不同的进程可以实现通信了,这样就能互相标记对方的唯一性,所以在通信的过程中,只需要在报文中携带原来ip的端口,并且把这个端口想办法传递给另外一个主机,那么这种基于ip地址和端口的通信方式,就叫做是socket,那么socket本身来说也就是ip地址加上端口号就是socket本身的含义
为了更方便的对于端口号进行描述,画出下面的这张图:
假设现在作为用户端,发起了一个请求,我想在抖音上看一个视频,而在非常远的另外一个地方有一个抖音的服务器,这个抖音的服务器端口号叫做8080,客户端的端口号叫做4321,那现在想要获取一个视频,内部就会封装一个对应的协议报头,自上而下进行不断的封装,封装到传输层的时候会记录下来当前的端口和目标的端口,这两个信息就都会被封装到传输层的报头中,此时这个报头就会继续传递,在网络层又会进行一个封包,封装了关于ip地址的信息,再继续向下封装,直到到物理层,再传递给抖音服务器的网卡,传递过去之后,再进行不断的解包,此时会进行识别,是被到时从哪个端口号来的,要发给我本主机的8080,理论上来说当收到这个报文之后,就传递给了服务器,服务器再构建对应的包把信息传回来,此时在用户的手机上就能收到一个来自于抖音发送的短视频信息了
那上述就是有关整个传递流程的基本逻辑,那下面对于一些细节信息进行阐述
首先是,这个端口的绑定该如何理解?其实就是在传输层当中封装了一层哈希表,在这个哈希表当中每一个节点都对应了一个进程的PCB指针,当有信息来了之后,就要在这个哈希表中进行比对,如果这个哈希表中的位置已经被绑定了,那么此时当前端口号就不能再被绑定到当前端口了,所以说这个8080实际上会经过哈希运算,最终可以帮用户找到对应的抖音服务器的进程,再进行后续运算
下来的问题是,在Linux下一切皆文件,所以对于整个网络的系统来说,从进程的角度来看,网络其实本质上也是一个文件,那么进程是如何读取到这个数据的呢?文件有对应的缓冲区,所以网络也必然有对应的缓冲区的信息,那么只需要把网络中的有效载荷存放在文件的缓冲区中,就可以找到对应的信息了
所以在绑定的过程中,实际上就是把进程的PCB和系统中的哈希表进行了一个基本的关联,最终收到的效果是当收到报文的时候,默认可以执行相同的哈希算法来找到对应的进程的相关信息
进程与端口号
- 一个进程可以被多个端口号绑定吗?
答案是可以的,在之前的例子中强调的都是一个服务器只有一个绑定的端口号,但是事实上一个服务器上可以绑定多个端口号,也就是说未来写的一个进程如果是一个网络服务,那么这个网络服务想要绑定多个端口号是可以的,换句话说就是这个进程既可以监听来自端口号1的请求,也可以监听来自端口号2的请求,这都是可以的
- 多个进程可以绑定一个端口号吗?
这个自然是不能的,从前面的关于哈希表的结构中就可以看出,一个端口号如果被多个进程绑定了,那么想要找到的哈希信息就不唯一了,一个端口号只能绑定一个进程,未来通过这个端口号是要找进程的,如果一个端口号被多个进程绑定了,那它还如何通过端口号来找进程,进而去寻找服务呢?
总结
端口号和ip地址,都是用来起到一个标识的作用,其中对于端口号来说是用来标识唯一的一个进程,而ip地址是用来标识唯一的一个主机,那么借助这两个信息就可以在偌大的网络系统中找到一个特定的主机上的一个特定的进程,进而进行相关的信息输送或者是数据传递,也就是说,实际未来在进行通信的时候,根本就不是两个主机在进行通信,而是两个主机上的进程在进行通信,网络的本质不也是进程间通信吗?所以只是和原来的不同的是,这两个进程不是在一个主机上的,而是借助网络的力量来做到了把信息从一个主机传递到另外一个主机,并且还能让两个进程看到同一份资源,进而实现了对于通信的功能