RIVALSA网络日志

互联网协议基础

于2021-10-05发布

本文原本于2020年6月12日发布在 RIVALSA 知识分享板块中,由于 RIVALSA 知识分享板块已下线,于2021年10月5日将本文转移至 RIVALSA 网络日志中。

为了扩大本文的受众群体,我们对互联网协议进行了简化,旨在表达清楚互联网通信的基本原理(重点在数据链路层和网络层)。

协议(protocol)是为了实现某个功能而制定的,需要共同遵守的规则。互联网协议是由一系列复杂、庞大的协议组成的,是互联网的核心,它规定了主机之间如何连接并组网。

互联网是一种分层的结构,每一层都有自身的功能,底层提供基础服务,顶层在应用底层服务的基础上做出了一些新的规定。而用户直接接触到的是最顶层的结构,并没有感知到下层的存在。但为了说清楚互联网协议,我们必须从最底层开始,逐渐向上。通常按照不同的模型,可以将互联网分成不同数量的层级,本文以五层模型来解释互联网协议。

五层网络模型

在五层模型中,物理层位于最底层,最靠近硬件,应用层位于最高层,最靠近用户。在每一层中都定义了很多协议,称为TCP/IP协议族,它们就是互联网的核心。下面从最底层开始简单的介绍主要协议。

1 物理层

物理层的目的就是把主机连接起来,连接的介质有多种多样的,比如光纤、网线、无线电波等。按照自身的协议来传送二进制信号,协议中规定了如何表示二进制1,如何表示二进制0等内容。发送方只需要按照协议将二进制数据调制为光信号、电信号等,在通过介质进行传输,接收方接收到光信号、电信号后按照协议解调为二进制数据即可完成数据的传输。

物理层解决了两台主机主机相互通信的问题,但当一台主机同时与其他多台主机相连时,通过物理层就无法仅向特定的相连主机传输数据了。

2 数据链路层

在数据链路层中以太网(Ethernet)协议占据主导地位。以太网协议规定,一组二进制数据构成一个数据包,也称为帧(Frame),每个数据包分成两部分:报头(head)数据(data)。以太网数据包的报头中有记录了一些基本信息,如数据发送方、数据接收方、上层使用协议等,数据中填充的就是实际要传输的内容。

以太网数据包

2.1 MAC地址

为了表示出发送方和接收方,以太网协议规定所有用于收发数据包的组件(网卡)都需要有一个全球唯一的网络地址,这就是MAC地址。MAC地址在网卡出厂时就固定了,由48位二进制数组成,为了方便我们读写,通常将其表示为12位十六进制数,并两位一分隔,通常表示为:12-34-56-78-9A-BC或12:34:56:78:9A:BC。其中,前6位十六进制数是网卡生产厂商的编号,后6位十六进制数是此网卡在此厂商内的流水号。还有一个特殊的MAC地址FF-FF-FF-FF-FF-FF这个地址表示所有的网卡。

虽然有了MAC地址,我们看起来似乎可以向地址为11-11-11-11-11-11的网卡发送数据了,但实际并非如此,因为发送方也并不知道相连的哪台主机的地址为11-11-11-11-11-11。

2.2 广播

假设我们有一个如下网络。

网络结构图

现在主机A要给CC-CC-CC-CC-CC-CC(即主机C)发送数据,主机A会根据以太网协议构建一个数据包,报头中部分内容如下。

以太网报头
发送方MAC地址:AA-AA-AA-AA-AA-AA
接收方MAC地址:CC-CC-CC-CC-CC-CC
上层使用协议:(某协议代码)

但由于并不知道哪台主机是CC-CC-CC-CC-CC-CC,无法准确的把数据包送达接收方,于是只能向网络内所有主机发送数据包,这种向网络内所有主机发送数据包的行为称为广播

这时主机B、主机C、主机D、主机E都收到了这个数据包,它们都会根据以太网协议来解读这个数据包。主机B、主机D和主机E从报头中看到这个数据包的接收方不是自己(因为接收方的MAC地址和自己的MAC地址不一致,也不是FF-FF-FF-FF-FF-FF),于是就忽略了此数据包(称为丢包)。主机C从报头中看到这个数据包的接收方是自己,于是继续处理数据包的数据部分。

根据以太网协议,要想发送数据包必须发送方和接收方有物理介质相连,比如上例中的主机C就无法向主机B、主机D和主机E发送数据包。要想它们之间能相互通信,就需要用物理介质将它们两两相连,这实在是太麻烦了。

2.3 交换机

交换机具有多个网络接口,当交换机收到数据包时,会将收到的数据包向其他所有接口进行广播。

有了交换机,我们可以将每一台主机直接与交换机相连,由于交换机内部对数据包转发的机制,就相当于我们把每一台主机两两相连了。那么,我们能否把全球的所有主机都连接到一台或多台交换机上,达到互联网的效果呢?从效果上讲是可以的,但这也存在一个问题,由于以太网协议发送数据包是通过广播的方式发送,无论哪一台主机发送数据包,都会导致全球的用户都收到这个数据包,都要对这个数据包进行处理,这显然是一场灾难。

3 网络层

为了防止某个主机发送数据包时,其他所有主机都能收到,我们采用划分子网的方式将网络分块。我们假设有一个如下网络。

网络结构图

上图中,主机A有两块网卡,其他主机均是一块网卡。

显然,主机D、主机E、主机A之间可以相互发送数据包,主机B、主机C、主机A之间也能发送数据包,但图中左右两侧的主机之间无法相互发送数据包了。我们通常把能互相发送数据包的网络称为一个子网

要想在划分了子网的网络中通信,我们首先应该让主机知道,数据包的接收方与自己是否在同一个子网中,由于MAC地址只与网卡的厂家及其序列号有关,与所处网络没有任何关系,所以我们无法通过MAC地址来判断接收方是否与自己处于同一子网中。这时,我们就需要另一个网络地址,这个网络地址是由网络管理员分配的,对于同一个子网的网络地址有共同的规律,于是我们就可以根据这个网络地址来判断接收方是否与自己处于同一子网中。

3.1 IP协议

IP协议中规定了前面提到的网络地址,由IP协议规定的网络地址称为IP地址。目前广泛采用的是IP协议的第四版(IPv4)和第六版(IPv6),本文主要以IPv4为例进行介绍。

IPv4规定,IP地址由32位二进制数组成,为了方便我们读写,通常将其按每8位分成一组,转换为十进制,并用点分隔,称为点分十进制

在IP地址诞生初期,将其分为了5类,二进制以0开头的称为A类IP地址,二进制以10开头的称为B类IP地址,二进制以110开头的称为C类IP地址,二进制以1110开头的称为D类IP地址,二进制以1111开头的称为E类IP地址。其中D类IP地址用于组播(也称为多播,本文不涉及),E类IP地址留给未来使用,A类、B类和C类的IP地址按照一定规则分配给人们使用。A类IP地址的二进制前8位为网络号,其余为主机号,B类IP地址二进制的前16位为网络号,其余为主机号,C类IP地址二进制的前24位为网络号,其余为主机号。当两个IP地址为同一类且网络号相同时,就认为它们处于同一子网中。

但随着网络的发展,出现了非常多的小型子网,比如一台路由器下只有3部手机2台电脑,无论分配哪类IP地址也会造成大量地址空闲却无法被其他网络使用的浪费情况。所以,目前我们通常由网络管理员自由指定IP地址中网络号的长度,子网掩码就是标记网络号这个长度的参数。子网掩码也是一组32位二进制数,其前若干位均位1,剩余位数均为0,其1的数量就是IP地址中网络号的长度。主机在判断两个IP地址是否处于同一子网时,只需要先判断双方子网掩码是否一致,如果一致再将双方IP地址与对应的子网掩码按位求与,如果运算结果也相同,则表示两个IP地址处于同一子网中,否则表示两个IP地址不处于同一子网中。

举例

现有两个IP地址,分别为10.255.46.2和10.129.0.0,其子网掩码均为255.128.0.0,它们是否在同一个子网?

由于两个IP地址对应的子网掩码相同,且IP地址与对应的子网掩码按位求与的结果均为255.128.0.0,所以它们是在同一个子网中的。

在IP地址中有两类特殊的地址,一类是主机号全为0的IP地址,这个地址表示这个子网,另一类是主机号全为1的IP地址,这个地址表示这个子网下的所有主机。

下面我们再说一下IP数据包,与以太网数据包相似,IP数据包也是由IP报头和数据组成。IP报头中主要包含IP协议版本、发送方IP地址、接收方IP地址、上层使用的协议等内容,数据中填充的就是传输的数据内容。

IP数据包

有了IP数据包后,怎么把这个数据包传送给接收方呢?当然是借助以太网数据包,我们只需要把IP数据包的内容放入以太网数据包的数据部分即可,此时,我们使用的数据包就变成了下图这样。

数据包

我们假设有一个如下网络。

网络结构图

现在主机B要给主机C发送数据,主机B发现它与主机C在同一个子网中。那么主机B就具有了向主机C发送数据包的条件了,这时我们只要再得知主机C的MAC地址就能顺利发送数据包了。

3.2 ARP协议

地址解析协议(Address Resolution Protocol, ARP)是根据IP地址获得MAC地址的一个协议,其数据包中包含发送方IP地址、接收方IP地址等内容。

以上图中主机B已知主机C的IP地址,想获得主机C的MAC地址为例,说明ARP协议的工作过程。

首先,主机B构造一个数据包,报头及数据中部分内容如下。

以太网报头
发送方MAC地址:(主机B的MAC地址)
接收方MAC地址:FF-FF-FF-FF-FF-FF
上层使用协议:(ARP协议的代码)
数据(即ARP数据包)
发送方IP地址:1.0.0.1
接收方IP地址:1.0.0.2

主机B将这个数据包在子网内广播,此时主机C与主机A都能收到这个数据包。当主机A收到这个数据包后,会根据以太网协议提取出ARP数据包,再根据ARP协议解读,看到接收方IP地址并不是本机的IP,于是丢包处理;主机C也会根据以太网协议提取出ARP数据包,但在解读ARP数据包时,看到接收方的IP地址是本机IP,于是将自己的MAC地址回复给主机B。

知识扩展

通常每个主机都会缓存一个ARP列表,当主机收到数据包时,就会直接将MAC地址与IP地址的对应关系缓存。当发送数据包时,如果缓存中有对应IP地址的MAC地址,就会直接使用此地址而不会再发送ARP请求。

ARP请求通常用于查询某IP地址对应的MAC地址,但也有一些特殊用法,比如某主机主动发送ARP请求,查询自己的IP地址对应的MAC地址,我们把这种请求称为免费ARP请求。这么做的目的有两个:1.把自己的IP地址与MAC地址的关系告知子网内的所有主机,让其他主机将自己的IP地址与MAC地址的对应关系存入缓存;2.查询子网中是否有IP地址与本机重复(若收到回复,则表示子网中有重复的IP地址),若发现IP地址重复,则在本机中给出提示。

有了ARP协议,我们就可以通过IP地址与子网中的任何一台主机进行通信了。那么跨子网的主机之间如何通信呢?

3.3 路由

路由(route)是指数据从原地址到到目的地址所走的一个路径,在每一台主机中都会保存了一个路由表。路由表(routing table)也称为路由择域信息库(routing information base, RIB),在其中存储着指向特定网络的路径。在路由表中至少有如下信息:网络IP地址、子网掩码、下一跳IP地址。当主机发送数据包时,如果接收方IP地址与本机IP地址不在同一个子网中,主机会在路由表中查找接收方IP地址属于路由表中的哪个网络,查到后会将数据包转发给对应的下一跳地址。

我们假设有一个如下网络。

网络结构图

现在主机B想给主机D发送数据,主机B发现它与主机D不在同一个子网中,于是主机B会在自己的路由表中查找主机D所属的网络,并得到路由表中下一跳的IP地址。假设在路由表中查询到的数据中部分内容如下。

网络IP地址:2.0.0.0

子网掩码:255.255.255.0

下一跳IP地址:1.0.0.3

通过子网掩码可以看出,网络IP地址中前24位为网络号,后8位为主机号。因为主机号全为0,所以这个IP地址表示一个子网,由于网络IP地址、主机D的IP地址与对应的子网掩码按位求与的结果相同,所以可得出主机D在这个子网中,所以这一条记录就是我们要查询的记录。

通过查询路由表,得到了下一跳的IP地址为1.0.0.3,于是主机B会构建一个数据包,报头中部分内容如下。

以太网报头
发送方MAC地址:(主机B的MAC地址)
接收方MAC地址:(主机A网卡1的MAC地址)
上层使用协议:(IP协议的代码)
IP报头
发送方IP地址:1.0.0.1
接收方IP地址:2.0.0.3
上层使用的协议:(某协议的代码)

主机B会把这个数据包发送给主机A,主机A收到这个数据包后,根据以太网协议提取IP数据包,从再根据IP协议解读这个IP数据包,发现接受方地址是2.0.0.3,不是自己,于是会将这个IP数据包再加上以太网的报头,并转发给2.0.0.3,即主机D。从主机A向主机D的数据包报头中部分内容如下,转发的过程不在赘述。

以太网报头
发送方MAC地址:(主机A网卡B的MAC地址)
接收方MAC地址:(主机D的MAC地址)
上层使用协议:(IP协议的代码)
IP报头
发送方IP地址:1.0.0.1
接收方IP地址:2.0.0.3
上层使用的协议:(某协议的代码)

这样,我们就完成了不同子网之间的通信,到目前为止,网络中的任何两个主机都可以互相通信了。

但随着网络的发展,我们的主机已经由专用的变成通用的了,一台主机中往往运行着很多程序,那么当这台主机收到数据包并提取出其中的数据后该交给那个程序来处理呢?(你可以想象电脑里开着一个网页,运行了一个QQ,这是网络里传来了一句话,电脑该把这句话显示在QQ里,还是显示在浏览器中呢?)

4 传输层

用来表示传输的数据包时供哪段程序使用的参数称为端口(port),端口是由16位二进制数组成了,为了方便我们读写,通常转换成十进制来表示。从0到1023的端口一般都是为特定的程序预留的,所以用户自定义的端口需要大于1023,无论您在QQ上聊天,还是浏览网页,都会占用一个端口。

当主机上由程序需要联网时,本地操作系统就会给这个程序分配端口,随后这个程序就负责处理所有携带这个端口号的数据包,称为监听某端口。如果说网络层的通信是从主机到主机的通信,那么传输层的通信就是从程序到程序的通信,在Unix系统中把“主机+端口”称为套接字

为了在数据包中加入端口号,人们在传输层上定义一些协议。

UDP协议非常简单,UDP数据包分为UDP报头和数据两部分,UDP报头中包含发送方的端口号、接收方的端口号等信息。

UDP数据包

为了把UDP数据包传输给接收方,我们需要把UDP数据包放入IP数据包的数据部分,于是,我们使用的数据包又变成了下方的样子。

数据包

主机收到数据包后,就可以从UDP报头中查出接收方的端口号,从而交给指定程序处理。UDP协议的优势是简单,容易实现,缺陷就是可靠性差,没有确认机制,无法确定对方是否收到数据包。

除了UDP协议外,常用的还有TCP协议。TCP协议中设置了一些机制来保证来确认对方已经收到了数据包,但代价就是过程复杂、实现较困难,消耗资源多。

5 应用层

我们每天都在使用不同的应用程序,每个程序需要的数据格式各不相同,所以不同应用程序在应用层传输的数据都有所不同。但也有一些大家公认在使用的协议,比如:HTTP协议、FTP协议、DHCP协议、SMTP协议等。应用层的数据,通常之间放在TCP或UDP数据包的数据部分。

正是因为有了这些协议的支持,我们才能愉快的在互联网上冲浪。本文以数据链路层和网络层为主介绍了一些最常用的协议,后续可能还会发布协议详解,如有兴趣,敬请关注。

(正文完)

版权信息

本作品著作权归属 Rivalsa 所有,除非 Rivalsa 明确许可您使用,否则任何个人或组织不得以任何方式直接或间接的复制、伪造、转载、摘编、翻印、改编、演出或以其他方式使用本作品。

已获得2个赞0个差评

0条评论

发表评论(取消回复)

通知选项

确定

是否 AT 其他评论者

不 AT 任何人