当我们决定要谈谈网络的时候,我想在谈之前,有必要了解一下“协议”这个词。协议,定义了在俩个或者多个通信实体之间交换报文的格式和次序,以及报文发送、接收报文或者其他的事件所采取的动作。定义都比较晦涩,那就让我们来个例子吧。
假设我要向你(互不相识)询问一下当前的时间;
我首先和你说:你好,以示我想要和你交流(发出报文,请求通信)。而你回应我(收到报文,通信建立):你好,表明能够继续询问你了。我发出询问(发出报文,包含事件处理):几点了?你看了看表(采取动作),然后回答我(收到报文,包含结果),2:00了。之后我说,谢谢(请求结束通信)。你说,不客气(通信结束)。
以上就是我们日常生活中所使用的协议。相类比计算机,其实也是相差不多的。不同的是,计算机毕竟不是人,所以得指定很多的协议,以保障它们正常的通信。比如以下几个常见的传输协议,当然不了解也没有关系,之后会详细的提及。
-
超文本传输协议(HTTP,HyperText Transfer Protocol)
-
传输控制协议(TCP,Transmission Control Protocol)
-
因特网协议(IP,Internet Protocol)
-
地址解析协议(ARP,Address Resolution Protocol)
一、网络模型
既然存在多种协议,那么总需要一种结构把它们合理的组织在一起。而现如今的俩种模型,都是采用的层次结构。每一层通过在该层中执行某些动作或者使用直接下层的服务来提供服务。下面就先来看看这俩类分层结构:五层因特网模型(应用层,运输层,网络层,链路层,物理层)、七层SOI模型(应用层,表示层,会话层,运输层,网络层,链路层,物理层)。下面我们以五层模型为例,谈谈计算机网络。不过由于物理层涉及比较广,所以我们实际讨论的只有四层:应用层,运输层,网络层,链路层。
网络模型
-
应用层:就是网络应用程序及它们的应用层协议存在的地方,我们常把位于应用层要传递的信息称为报文(message)。
-
运输层:因特网的运输层负责在俩个应用程序端点之间传递应用层报文。在因特网中,有俩种运输协议,TCP和UDP,使用其中的任何一个都能传递应用层报文,值得注意的是,在这一层,TCP/UDP会把上层报文包装成一个新的结构,我们称为报文段(segment)。
-
网络层:在这一层,网络层也会把上一层的报文段包装成一个被称作数据报(datagram)的结构。然后把这个数据报从一台主机移动到另外一台主机上。在这一层就包括著名的IP协议。
-
链路层:同理,在这一层,又在数据报的外面加了个壳,我们把加壳之后的这个东西叫做帧(frame)。然后通过这一层把帧从当前的一个节点移动到下一个节点,网络层必须依靠链路层的服务。如下图,从源主机到链路交换机。
信息传递过程
在网络中,我们经常会忽略具体的设备,而统一称为主机(host),或者端系统(end system)。比如智能手机,平板电脑,电视,游戏机,web相机等等......而主机与主机之间通过通信链路(communication link)和分组交换机(packet switch)连接在一起。分组交换机各式各样,但当今最著名的类型是路由器(Router)和链路层交换机(Link-layer switch),分别也称为,三层交换机,或者俩层交换机。由上图可以看出。
最后,来说一个小程序,tracert。通过它,可以确定从你当前的主机到目的主机之间经过了那些交换机。
二、应用层
对于应用层,我想绝大多数人,应该是最熟悉的了。尤其是从事软件开发的人。这类应用程序体系结构是由应用程序研发者设计,不过多是利用的现代所流行的俩种主流体系结构之一:C/S结构(客户 - 服务器),P2P结构(对等体系)。
-
C/S结构:在这种体系中,总有一个需要一直打开的主机,我们称为服务器(server),它服务于其他称为客户(client)主机的请求。服务器总是具有一个固定的地址,大家都知道的地址,称为IP地址。比如baidu.com的IP地址之一为180.149.132.47。啥?你不知道baidu.com的地址,但是你知道baidu.com这个名字吧,又因为存在DNS服务(后面说),所以想当于了解。在这种结构下,值得注意的是,其他客户主机之间是不可以之间进行通信的。
-
P2P结构:在对等(Peer-to-peer)体系中,每台计算机之间都处于对等的地位,各台计算机有相同的功能,无主从之分,一台计算机既可作为服务器,设定共享资源供网络中其他计算机所使用,又可以作为工作站。网络中的每一台计算机既能充当网络服务的请求者,又对其它计算机的请求做出响应,提供资源、服务和内容。通常这些资源和服务包括:信息的共享和交换、计算资源(如CPU计算能力共享)、存储共享(如缓存和磁盘空间的使用)、网络共享、打印机共享等。
2x01.是什么在通信
对于学习过操作系统,或阅读过unix网络编程的人,对Tcp echo服务器应该不会陌生。当前进程通过fork()生成另外一个进程,一个进程发送一句话,然后另外一个接收到,并且显示在屏幕上。所以,我们可以想得到,在应用层而言,忽略下层数据传输细节,那么通信的其实就是进程。然而我们不怎么关注同一台主机上进程间的通信,而关注不同端系统上的进程间的通信。那么就不得不一个新东西:套接字,主机上应用层与运输层的接口,但是应用程序开发者对于运输层的控制仅限于:
-
选择运输层的协议
-
也许能设定几个运输层的参数,比如最大换成数,和最大报文段长度等。
2x02.网络应用
互联网从诞生到现在不过短短百年,但是对于人类社会的影响确实翻天覆地。试想,一百年前的时候,你能身处中华,却知道美国现在发生着选举大会吗?你能通过一个东西随身携带万卷书吗?你能实时与你远在他乡的好友实时通讯吗?不能,都不能。但是现在可以。那么接下来,就介绍几个极为流行的应用以及它的应用层协议吧。
-
HTTP:Hyper Text Transfer Protocol(超文本传输协议)的缩写。常有俩个程序实现,客户机-服务器,并且分别运行在不同的端系统上。其下的支撑运输协议是使用的TCP,而且由于http服务器并不保存关于客户的任何信息,所以http也被称为是一个无状态协议。但是为了跟踪用户的输入(比如用户的购物车商品),网站会提供一个用户身份的识别码,存放在cookie中,每次再访问网站则自动将cookie加入到HTTP报文头部,实现身份的识别。
交互过程
-
FTP:File Transfer Protocol(文件传输协议)的英文简称,而中文简称为“文传协议”。同时,它也是一个应用程序。通过使用俩个并行的TCP链接来传输文件,一个是控制链接,一个是数据链接,控制链接用于在俩个主机之间传输控制信息,如用户标识,口令,命令。数据链接用于实际发送一个。
-
DNS:Domain Name System(域名系统)的缩写,运行在UDP协议之上。就像我们上面提到的baidu.com怎么转换成ip地址,这个就是DNS的服务。下面来介绍一下。首先,总的来说,DNS采用了分布式的设计方案。如下。
https://img-blog.csdnimg.cn/img_convert/b374084d9e34ca80f67bdfdc91f100e8.webp?x-oss-process=image/format,png" width="671" />
DNS服务器层次结构
每个组织,如一个大学,一个院系,一个公司都会有一台本地DNS服务器,当一台主机想要访问baidu.com的ip地址时,会先发送她的查询请求到本地DNS服务器,里面查找是否有baidu.com的ip地址。没有的话,本地DNS服务器就把这个请求转发到根DNS服务器,然后根DNS服务器把comDNS服务器地址发送给本地DNS服务器,然后本地DNS服务器发送查询请求到comDNS服务器,完成名字与ip地址的转换。
如果你想在你的主机上发送一个DNS查询报文,那么就使用nslookup程序吧,它可以帮助你完成,前俩行是你的主机的DNS服务器的名字,以及ip地址。
三、运输层
运输层协议为运行在不同的主机上的应用进程之间提供了逻辑通信,不需要考虑下层的实现细节,即使是相隔很远,也可以通过运用运输层的接口彼此发送报文。所以运输层协议是在端系统上而不是在路由器上。我们通过应用层,都知道,俩个主机之间通信就是俩个进程在通信。但是我们的电脑经常运行着很多的软件,QQ、网易云音乐、chrome.......那么怎么保证它们正常接收到自己的数据包呢?这里就要提出一个叫做端口的东西。端口,是一个16比特的数,其大小在0-65535之间,但是0-1023范围的端口称为公认端口,它们紧密绑定于一些服务。通常这些端口的通讯明确表明了某种服务的协议。例如:80端口实际上总是HTTP通讯,FTP一般使用端口(20,21),53为DNS服务的端口等等。
多路复用/分解:一个进程可以有一个或者多个套接字,就像FTP,但是一般一个套接字值绑定只一个端口号,那么在同一个时刻,一定存在着多个套接字,所以每个套接字都有自己唯一的标识符。用来区别于其他套接字。这样运输层就可以把不同的报文数据交付到正确的套接字上面,称为多路分解。而不同的套接字加上各种的壳,从而生成报文段,然后将报文段传递到网络层,称为多路复用。
3x01.UDP
为了说清楚UDP(User Datagram Protocol)协议,我想有必要简单的说明一下网络层的IP协议。IP协议的服务模型为尽力而为交付服务,这就意味着IP尽它“最大的努力”在通信的主机之间交付报文,但它不会做任何的保证。不保证报文段的交付,不保证报文段的按序交付,不保证报文段中数据的完整性。所以IP协议也被称为是不可靠服务。
就像IP协议是不可靠协议一般,UDP也是如此。但是尽管如此,有一些场合,还是很适合UDP的,比如交谈式音频/视频,这些应用能够承受一定程度的数据损失,因为那丢失的数据对于播放出现的干扰,并不是很致命。如果说应用程序开发人员在开发时选择了UDP,那么这个应用差不多就是直接与IP协议打交道了。我知道,你想说,既然UDP这么不好,为什么编程有时还选择这个。那是因为UDP在传输的速度上要很大的优于TCP协议。TCP提供很多的保障,但是保障的背后就是时间的代价。就像在相同算法下,C语言与其他高级语言运行时间明显有差别。
UDP报文段结构
上图为UDP报文段结构,我们可以看出,相比较上层(应用层)传来的报文,多了四个字节,分别为,源端口号,目的端口号,长度(报文),校验和。通过后俩个传输数据,确定是否在移动中,其中的比特发生了改变。比如链路中的噪音干扰,或者存储在路由器时引入问题。有人可能会说怎么这个报文段里面没有对方或者自己的IP地址,那时因为IP地址是在下一层包装进去的。
3x02.TCP
tcp(Transmission Control Protocol)协议相比叫UDP协议,最为重要的就是比UDP多了俩项功能。
-
可靠传输。保证数据正确、按序到达。虽然UDP不能保证,但是可以在上层应用程序里建立自己的可靠机制来完成。
-
拥堵控制。由于UDP没有限制发送报文段,所以导致UDP发送方和接受方之间的高丢包率,并挤跨了TCP的会话。
https://img-blog.csdnimg.cn/img_convert/6b1f3d9cf4caa492f540673914a1b40c.webp?x-oss-process=image/format,png" width="661" />
TCP报文段结构
三次握手:
-
在报文段的首部中的一个标志位SYN被置为1,所以,有时也称其为SYN报文段,另外,客户会随机的选择一个初始序号(client_isn)并放到序号(Sequence number) 。然后发送给服务器。
-
服务器会从该数据报中提取SYN报文段,并且为TCP连接分配TCP缓存和变量,并向该TCP发送允许连接的报文段。其具体为:首先,SYN置为1;其次,首部的确认字段(Acknowledgment number)被置为(client_isn + 1),最后会选择自己的初始序号(server_isn)放到序号(Sequence number) 。然后发送给客户机。有时也称这个报文段为SYN报文段(SYNACK segment)。
-
在客户机收到SYN报文段后,客户机也要给该连接分配缓存和变量,然后给服务器发送一个确认报文段。对服务器的允许连接的报文段进行确认。连接建立之后,该SYN被置为0。
三次握手
四次挥手:
-
客户机想服务器发送一个特殊的报文段,这个报文段让其首部的标志位FIN被置为1,然后发送给服务器。
-
当服务器接受到该报文的时候,就向客户机发送一个确定报文。
-
服务器发送自己的终止报文段,其FIN被置为1。
-
客户机对这个服务器终止报文段进行确认。
四次挥手
由于TCP并没有提供任何的加密机制,所以现在研制了TCP的加强版本,称为安全套接字(Secure Sockets Layer,SSL)。用SSL加强后的TCP不仅能够完成传统TCP所能做的一切,而且提供了关键的进程到进程的安全性服务。
四、网络层
网络层的作用从表面上看极为简单,就是把数据报从一台主机移动到另外一台主机上,为此,需要俩种重要的功能。当然,这一层有上面提到的IP(Internet Protocol)协议。
-
转发。数据报从单一的路由器中从一条入链路到出链路的传送。
-
路由选择。一个网络中所有的路由器,它们经路由选择协议共同交互,以决定数据报从源到目的地所采用的路径。
https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=https%3A%2F%2Fp9-jj.byteimg.com%2Ftos-cn-i-t2oaga2asx%2Fgold-assets%2Fe618a6374f47f27f7999~tplv-t2oaga2asx-jj-mark%3A3024%3A0%3A0%3A0%3Aq75.awebp&pos_id=8aI6MNRR" width="534" />
转发
在实际的网络中,每一个路由器,都会有多个输入端,就像(A,B),和多个输出端。并且在输入端使用了存储转发传输机制,这种机制是指在每个路由器能够开始向输出端传输该数据报的第一个比特之前,必须接受整个数据报。而在每一个输出端,都具有一个输出队列,它用于存储路由器准备发送到这个输出端的数据报。当然,既然是队列,还是在实际情况下,那么总会有输出队列被充满的时候,这个时候就会出现丢包(packet lost),到达的数据报或者已经在排队的数据报之一会被丢弃。
4x01.IPv4编址
我们知道,主机,路由器是通过一条条的物理链路链接在一起,而主机/路由器与物理链路的边界,我们常称其为接口。在ip协议中,要求每台主机/路由器的每个接口都拥有自己的ip地址,也就是说,一个路由器可能有多个ip地址。在IPv4中,规定IP地址长度为32比特,等价于四个字节。每字节最大255,所以ip最大为255.255.255.255。这些地址一般使用所谓的点分十进制记法书写,即地址中的每个字节用它的十进制书写,各字节之间以句点隔开。例如127.0.0.1。
https://img-blog.csdnimg.cn/img_convert/b730d5b7eda5a63d153e8a7737490dda.webp?x-oss-process=image/format,png" width="626" />
IPv4编址
用ip的术语来说,互联的三个主机和一个路由器接口形成一个子网。ip编址为这个子网分配了一个地址:233.1.1.0/24,其中/24记法,有时也被称为子网掩码,指示了32比特中的最左24比特定义了子网地址。其他要连接在这个233.1.1.0/24网络的主机,其地址要求具有233.1.1.xxx的形式。ip地址通过限制特定长度的比特,对ip进行分类编址。如下。
类型 | 范围 |
---|---|
A | 0.0.0.0 - 127.255.255.255 |
B | 128.0.0.0 - 191.255.255.255 |
C | 192.0.0.0 - 223.255.255.255 |
D | 224.0.0.0 - 239.255.255.255 |
E | 240.0.0.0 - 255.255.255.255 |
4x02.DHCP
试想,如果一个组织一旦获得一块地址,那么它就可以为本组织内的主机与路由器接口逐个分配ip地址。那么就不得不提出DHCP(Dynamic Host Configuration Protocol,动态主机配置协议)协议了。DHCP具有将主机连接进一个网络的网络相关方面的自动能力,在早期,对于网络管理员,不得不手动执行这些认为任务,所以它的出现对于网络管理员非常吸引。
https://img-blog.csdnimg.cn/img_convert/bdbbca3e1a6cbdbbc35849af5d9860e4.webp?x-oss-process=image/format,png" width="671" />
DNCP服务器
DHCP建立过程:
-
DHCP客户端发送DHCP discover消息(IP地址租用申请),这个消息是通过广播方式发送出去的,所有网络中的DHCP服务器都将接收到这个消息。
-
网络中的DHCP服务器会回应一个DHCP offer消息(IP地址租用提供),由于这个时候客户端还没有网络地址,所以DHCP offer也是通过广播的方式发送出去的。需要注意的是,由于网络中可能存在不止一台的DHCP服务器,所以,如果不考虑网络丢包的话,客户端将接收到不止一条的DHCP offer消息。那么客户端会选择它接收到的第一条DHCP offer作为获取配置的服务器。
-
客户机向该服务器发送DHCP request消息。虽然这个时候客户端已经明确知道选择的DHCP服务器的地址所在,但仍将采用广播的方式发送DHCP request消息,这样做不仅可以通知选中的服务器向客户端分配IP地址,同时也可以通知其他没有选中的DHCP服务器不需要再响应它的请求。在DHCP request消息中将包含客户端申请的IP地址。
-
DHCP服务器将回送DHCP ACK的响应消息对请求报文进行响应。
DHCP客户-服务器交互
五、链路层
对于一个主机体系结构,链路层的主题部分是在网络适配器中实现的(有时也被称为网络接口卡)。而在网络适配器也具有自己的链路层地址。链路层的地址有各种不同的叫法:LAN地址(LAN address),物理地址(physical address),MAC地址(MAC 地址)。
既然有了网络层ip地址,为什么还要链路层的mac地址?那是因为要保证每层的独立性,假如在链路层的上层不是网络层,那么链路层该如何寻址?所以引入mac 地址。
那么在网络层和链路层之间适合转化的呢。这就是地址解析协议(ARP,Address Resolution Protocol)的功劳。ARP将一个ip地址解析为MAC地址的时候,很多方面与DNS类似。虽然DNS是将主机名解析成ip地址。