OSI网络七层模型简介
网络七层模型就是一个参考模型,也就是说有这么个七层的定义,就像是项目中的dao、server、controller三层架构一样,每一层都有自己的工作要干,互联网协议就按照不同的作用分为osi七层或tcp/ip五层或tcp/ip四层。
应用层
第一层:应用层。定义了用于在网络中进行通信和传输数据的接口
第二层:表示层。定义不同的系统中数据的传输格式,编码和解码规范等
第三层:会话层。管理用户的会话,控制用户间逻辑连接的建立和中断
传输层
第四层:传输层。管理着网络中的端到端的数据传输
网络层
第五层:网络层。定义网络设备间如何传输数据
链路层(网络接口层)
第六层:链路层。将上面的网络层的数据包封装成数据帧,便于物理层传输
第七层:物理层。这一层主要就是传输这些二进制数
学习计算机网络时我们一般采用折中的办法,也就是中和OSI和TCP/IP的优点,采用一种只有五层协议的体系结构学习即可,这样既简洁又能将概念阐述清楚。
网络通讯的流程了基本如下(五层):
应用层,数据(加http协议等)-》传输层(包上tcp或者udp协议)-》网络层(包上ip协议)-》数据链路层(包上以太网协议)-》物理层
下面就开始详细介绍这个几层,并按如上流程进行演示,最好开一台服务器或者虚拟机,跟着一起操作感受一下
应用层
比如浏览器、qq微信都是属于应用层,准确的说是应用层客户端,访问的服务器就是应用层服务端。我们在浏览器发送的请求会被加上http协议传输到传输层。还有xftp、sqlyong等等会加ssh协议。
这些协议就是所谓的应用层协议,用来约定两个程序传输的格式、怎么加密的等等。不同的场景选择不同的协议来工作。
其后的传输层、网络层、网络接口层我们并不需要关心,因为这是操作系统内核帮我们做好的事情了。就像我们使用浏览器一样,http协议浏览器帮我们加好了,只需要输入域名就可以。
用linux访问百度举个例子:
1.创建连接:8就代表文件描述符,<>代表输入输出,然后指向了一个路径,但是操作系统内核会把这个路径转换成对百度的socket连接
exec 8<> /dev/tcp/www.baidu.com/80
创建socket之后,cd到/proc目录下
这个目录下是内核程序运行时我们能在文件系统看到的东西,可以看到目录中有很多数字的目录,可以把他们想象成线程号一样。
如下命令就是查看当前执行进程的进程号,相当于查看当前运行的线程了。
echo $$
可以看到当前的进程号就是2955,那么进入2955
可以看到一些目录,这个fd就是前面说的文件操作符了,再cd进去,ll查看
0代表标准输入,1代表标准输出,2代表报错,下面的8就是我们刚才创建的socket,指向的百度。
那么我们现在其实就是应用层客户端,我们已经有了应用服务端百度的连接,那么我现在应该遵循某种协议,给百度发一些信息,让百度把主页返回给我们。现在很明显我们应该遵循HTTP协议。
2.发送请求:请求的HTTP协议规范为 “GET / HTTP/1.0\n”,最后\n就是换行符,-e代表识别换行符,>代表会写到文件中,>&就代表会写到文件描述符中。
echo -e "GET / HTTP/1.0\n" >& 8
通过执行上面命令,就会把“GET / HTTP/1.0\n”通过8号文件描述符发送给百度,我们8号文件描述符的这个socket连接是双向的,可输入输出,那么百度就会把主页的信息放到socket中,我们只需要把8文件描述符的数据输入重定向出来,就可以看到百度主页的信息了
cat <& 8
上面我们干的其实就是一个应用层做的事,传输层网络层我们是无感的,因为系统内核已经把TCP协议的事做了,后面我们继续深入研究系统内核怎么做的TCP协议。
我们想一下刚才就做了两步,通过exec建立连接,发请求。那么怎么从应用层到的传输层、网络层的呢,其实太明显了,传输就是socket做的嘛,所以exec创建socket时就是调用了内核的传输层才建立的socket。
传输层
传输层就是把一台计算机的数据传输到另一台,基于的协议可以是TCP或者UDP,TCP是面向连接并可靠的协议,那么什么叫面向连接还可靠的呢,他要通过三次握手,四次挥手来保证它的可靠性。
三次握手
什么是三次握手呢,其实就像下图一样,由客户端这边的传输层创建了一个sync数据包发给服务端,代表我想和你建立握手,服务端如果能收到这个包,一般服务端的传输层会给客户端回一个sync+ack确定包,最后客户端还得再给客户端回一个确认包,这样就通过三次握手建立了连接。
再来解释一下为什么需要三次握手,我们建立的socket这种网络通信是双向的,也就是客户端也发送有接收,服务端也有接受和发送,我们就需要让客户端和服务端都必须确定自己的接收和发送的是通的,那么最少需要三次,才能确定一个可用的socket。
一旦双方通过三次握手确认了自己的输入输出没有问题,这时候怎么建立连接呢,连接并不是一个实质性的连接,而是双方专门开辟出一块资源,这个资源有可能是一个进程,也可能是java当中一个线程,它是专门为对方而准备,然后就可以完成后面后续的通信过程,这就是所谓的面向连接。
如下这段代码其实就是开启一个socket,然后如果有客户端连接进来,等三次握手成功了,就能通过socket对象的accept方法拿到连接,然后开启个线程处理它,进而完成后续的数据读取与写入。
这时候我们再想一下应用层干的事,把应用层和传输层结合起来,其实就是应用层把那个http协议传给了传输层,传输层又把它封装成数据包,然后三次握手建立连接,最后发送出去。
四次挥手(四次分手)
当双方完成交互,要做的事情干完了,就要断开连接,断开连接其实就是释放开辟的资源。那我们断开是想断开就能断开嘛,并不能,因为我们的资源是为对方服务的,所以需要对方知道并且同意了我们才能断开。
如上图,假如是客户端想断开,那么客户端的传输层会创建一个Fin数据包,服务端收到后,会回送一个ACK包,回的意思是我知道你想断开了,但是并没有同意断开呢,服务端还需要再发送一个Fin数据包,代表我同意断开了,客户端再回一个我收到了。俩次的断开都是各自发出的,以保证双方安全的释放掉资源。
如果超时了或者其他原因导致没有完成四次分手,那么时间过了,太久没响应,自己也会把资源释放掉了。
思考
这时候其实对网络通讯已经比较了解了,那么我们再来想一个问题,比如我们浏览器打开十个标签页,搜索不同的东西,为什么搜索的结果没有传乱了呢,可以想到他们每个标签都是不同的连接,不同的socket,那么大家对socket的认知恐怕只知道他是一个套接字。
其实可以把他理解为“Ip-port ip-port”,两台计算机的ip和端口组成唯一映射关系。这个在Linux系统当中也可以体现出来
输入命令,netstat代表网络状态, n就是忽略地址到ip的翻译,a就是所有,t就是tcp,p就是显示id号和进程
netstat -natp
前面的是本机的ip和prot,后面的是对端的ip和prot,这一对就可以理解为套接字socket,我们还可以注意一下第一列,端口号的22,并且还是sshd协议,LISTEN状态,就代表这个程序是一个Server服务端,开始监听我的22端口有没有人连接。
下面我们干一个有趣的事。
我们开启三个标签,创建了三个连接,是不是和刚才说到的浏览器标签是一样的感觉,那我们找到这三行进行对比
Linux服务器本机的ip地址和端口完全一样,这时候的对端就是连接服务器的window了,因为是同一台windows连接的服务器,所以ip相同,但是可以发现端口号不同,打开的标签页都和windows申请了唯一的随机端口号,最终可以区分这几个socket。
但是端口是数量有限的(0-65535),所以事情做完会断开连接释放资源,释放端口号。
网络层
传输层会帮我们做三次握手,创建数据包,但是是在网络层发出去的。也就是在创建握手包之后他是调向网络层的,网络层对应的就是IP协议了。
这里要说到一点就是经常会把TCP/IP说到一起,这个TCP/IP其实指的就是OSI模型,OSI的应用层对应HTTP、SSH等,传输层对用TCP,网络层对应IP,所以叫做TCP/IP,说的就是OSI模型了。
IP是互联网所有设备唯一标识的ID,网络层就是通过IP寻找到对方的路由路径,这时候我们考虑全球那么多IP,应该怎么去找到目标IP,在互联网里也是层级关系的,也就是先有小网也就是我们局域网,后有大网就是我们的互联网。从互联网中找到局域网,在从局域网中找到目标IP。所以我们IP中相当于有两个信息,一个是自己的名字,一个是归属于哪个局域网。
首先查一下我们ip信息
ifconfig
可以看到ip地址,广播地址和掩码,那么他们怎么来的
打开网卡配置文件,if是interface,cfg是config,eth就是以太网,0就是第一块网卡
vi /etc/sysconfig/network-scripts/ifcfg-eth0
可以看到上面有device是eth0这个设备,硬件地址、开机启动等等,最下面两个DNS是做域名向地址的解析。但是传输层创建的数据包,封的是ip,不是域名,这点需要知道,然后主要看我们下面的三行。
第一行是IP地址,第二行是子网掩码,第三行是网关。
这块需要了解二进制和十进制,不懂的百度一下吧,很简单。
我们先说IP和掩码的关系,IPV4是点分字节,也就是一个点两侧分别是一个字节Byte,一个字节有8个二进制位。
所以我们常说IPV4是32位的就是4*8(IPV6是128位),一个字节有8个二进制位那么最大就是11111111,最小00000000,二进制转十进制,11111111转为十进制就是255,也就是0-255。
IP清楚以后看掩码,掩码是三个255一个0,掩码和IP之间有个运算关系,叫做二进制的按位与运算,按位与运算就是全1为1,有0则0。
即(0&0=0; 0&1=0; 1&0=0; 1&1=1)
那么每一位做比较,192的二进制是11000000,255的二进制是11111111,所以得到的还是11000000,14的二进制和0的二进制做与运算得到的是0
也就是拿IP和掩码做完运算得到的是192.168.150.0,算出的192.168.150.0就是这台计算机所在的局域网,如果其他计算机能找到192.168.150这个局域网就能找到14号机。
然后我们先抛开GATEWAY网关,继续说IP,IP协议这层对应着一个路由表,我们可以想一下现在这个世界当中,手机,笔记本,台式机都是可以联网的,他们之间可以互相通讯,那么怎么手机怎么连接到服务器呢,互联网怎么互联的呢?
这里补充个知识点,比如我们ping了以下百度,他能在三四毫秒就能找到百度,我们读硬盘来读文件,磁头寻址读到目标文件的时间也是毫秒级别,我们再回想之前说的冯诺依曼体系,我们的硬盘、网卡都是输入输出设备,那么我们可以得出一个结论:在计算机系统当中IO是个瓶颈,他的延迟是毫秒级,因为内存的寻址时间是纳秒级别,内存比一切IO快了十万倍,所以说IO就是计算机系统中的瓶颈,从时间就是可以算出来。
说回来,毫秒对于人的体感来说已经足够快了,那么如何在这个庞大的互联网中快速的寻找到要访问的地址呢,其实在TCP/IP协议诞生的时候就解决了这个问题。通信很快但是它受到了学术界的抨击和质疑,为什么呢,因为它是采用的下一跳的传输方式。
下一跳是个什么机制什么概念呢,就和上图是一样的,比如上图三台计算机,a连b,b连c,a想访问c,它会直接把数据包扔给b,但是a并不知道能不能找的到,但它只有b这么一个出口,所以a会直接把数据包丢给直连的b,b再丢给c,这样都只扔给和自己直连的机器,就这样一跳一跳的就能有可能跳到目标计算机,当然也有可能跳丢了,这也就是学术界质疑的点。
为什么会采用这种下一跳的机制呢,因为我们面向每台主机,它不需要知道全局,只需要知道一个出口就可以了,所以前面提到的路由表就是要去完成这个下一跳机制。
我们来人肉模拟一下数据包出入选址的过程:
Linux系统中输入查看路由表命令
route -n
我们注意看第一行的信息,它的目标地址或者终点是192.168.150.0,网关是四个0,掩码是三个255一个0,那么这条信息哪来呢,就是刚才看到的网卡配置文件,拿着IP和掩码做完运算得到了网络号,然后通过eth0这块网卡,就可以和自己所的在的192.168.150.0这个局域网里的任何机器通信,且不需要网关。
第二行不需要看,接着看第三行,第三行的目标地址是四个0,网关是192.168.150.2,掩码是四个0,代表什么意思呢,比如我在ping百度
百度的域名通过DNS转换成了61.135.169.125这么一个目标地址,也就是说这台服务器会封装一个数据包,这个数据包的目标ip地址就是了61.135.169.125,然后我们的数据包应该去找哪块网卡呢,下一跳跳哪去呢,其实会有一个路由判定的过程
只需要拿着目标地址61.135.169.125和路由表当中的每一行掩码位做按位与运算,然后和前边的网络号比,不一样不匹配相当于作废,继续对比一下条
这时想想路由表的最后一行很神奇,掩码和目标地址全都是0,那么用任何的ip地址都能和最后一条匹配上,这个就叫做默认网关条目,也就是访问任何的地址都会和这个条目匹配上,这个条目中还有一个网关是192.168.150.2,也就是我们要把这个数据包扔给192.168.150.2,它去做下一跳去
猜猜这个网关是谁,太明显了,他就是路由器嘛,我们的路由器就是我们的网关,我们把数据包扔给路由器,路由器也有自己的路由表,它扔给运营商,运营商再扔给城域网,城域网再扔给骨干网,最终扔到我们要访问的服务器上去,这就是下一跳的过程
那么我们访问同一局域网怎么访问的,比如我们ping自己局域网内的一台机器
拿ip和掩码做完运算就走路由表的第一条了吧,并且没有网关
最后这里还有一个点,比如我们要访问百度,得把访问百度的数据包扔给了网关,那么这时候的数据包里面的ip地址是放路由的ip地址还是百度的ip地址?我们放网关的ip的话,到了网关,网关就以为是给它的数据包,就不会再有下一跳了,但是放百度的ip,连网关都找不到。所以一层是不够的,这时候就得有了下一层——链路层。
Comments | 0 条评论