完成IP模块的工作之后,下面就该轮到网卡了,不过在此之前,我们先来了解一些以太网的基本知识。 以太网是一种为多台计算机能够彼此自由和廉价地相互通信而设计的通信技术,它的原型如图(a)所示。从图上不难看出,这种网络的本质其实就是一根网线。图上还有一种叫作收发器的小设备,它的功能只是将不同网线之间的信号连接起来而已。因此,当一台计算机发送信号时, 信号就会通过网线流过整个网络,最终到达所有的设备。这就好像所有人待在一个大房间里,任何一个人说话,所有人都能够听到,同样地,这种网络中任何一台设备发送的信号所有设备都能接收到。不过,我们无法判断一个信号到底是发给谁的,因此需要在信号的开头加上接收者的信息,也就是地址。这样一来就能够判断信号的接收者了,与接收者地址匹配的设备就接收这个包,其他的设备则丢弃这个包,这样我们的包就送到指定的目的地了。
为了控制这一操作,我们就需要使用MAC头部。通过MAC头部中的接收方MAC地址,就能够知道包是发给谁的;而通过发送方 MAC地址,就能够知道包是谁发出的;此外,通过以太类型就可以判断包里面装了什么类型的内容。以太网其实就这么简单。
这个原型后来变成了图中的结构。这个结构是将主干网线替换成了一个中继式集线器,将收发器网线替换成了双绞线。不过,虽然网络的结构有所变化,但信号会发送给所有设备这一基本性质并没有改变。 后来,图(c)这样的使用交换式集线器的结构普及开来,现在我们说的以太网指的都是这样的结构。这个结构看上去和(b)很像,但其实里面有一个重要的变化,即信号会发送给所有设备这一性质变了,现在信号只会流到根据 MAC地址指定的设备,而不会到达其他设备了。当然,根据MAC 地址来传输包这一点并没有变,因此MAC头部的设计也得以保留。
尽管以太网经历了数次变迁,但其基本的 3 个性质至今仍未改变,即将包发送到 MAC 头部的接收方 MAC 地址代表的目的地,用发送方 MAC地址识别发送方,用以太类型识别包的内容。因此,大家可以认为具备这3 个性质的网络就是以太网 。
以太网中的各种设备也是基于以太网规格来工作的,不仅适用于客户端计算机,同样也适用于服务器、路由器等各种设备。 此外,以太网和IP一样,并不关心网络包的实际内容,因此以太网的收发操作也和 TCP的工作阶段无关,都是共通的。

2.如何收发以太网包

下面来看看以太网的包收发操作。IP 生成的网络包只是存放在内存中的一串数字信息,没有办法直接发送给对方。因此,我们需要将数字信息转换为电或光信号,才能在网线上传输,也就是说,这才是真正的数据发送过程。 负责执行这一操作的是网卡,但网卡也无法单独工作,要控制网卡还需要网卡驱动程序。驱动程序不只有网卡才有,键盘、鼠标、显卡、声卡等各种硬件设备都有。当然,不同厂商和型号的网卡在结构上有所不同, 因此网卡驱动程序也是厂商开发的专用程序。
网卡的内部结构如图所示,这是一张网卡主要构成要素的概念图,并不代表硬件的实际结构,但依然可以看清大体的思路。记住这一内部结构之后,我们再来介绍包收发的操作过程,现在,我们先来讲讲网卡的初始化过程。网卡并不是通上电之后就可以马上开始工作的,而是和其他硬件一样, 都需要进行初始化。也就是说,打开计算机启动操作系统的时候,网卡驱动程序会对硬件进行初始化操作,然后硬件才进入可以使用的状态。这些操作包括硬件错误检查、初始设置等步骤,这些步骤对于很多其他硬件也是共通的,但也有一些操作是以太网特有的,那就是在控制以太网收发操作的 MACA模块中设置MAC地址。网卡的 ROM 中保存着全世界唯一的 MAC 地址,这是在生产网卡时写入的,将这个值读出之后就可以对MAC模块进行设置,MAC模块就知道自己对应的 MAC地址了。也有一些特殊的方法,比如从命令或者配置 文件中读取 MAC地址并分配给MAC模块。这种情况下,网卡会忽略ROM 中的MAC地址。有人认为在网卡通电之后,ROM中的MAC地址就自动生效了,其实不然,真正生效的是网卡驱动进行初始化时在MAC模块中设置的那个 MAC地址。在操作系统启动并完成这些初始化操作之后,网卡就可以等待来自IP的委托了。

3.以太网接收网络包详细

在使用集线器的半双工模式以太网中,一台设备发送的信号会到达连接在集线器上的所有设备。这意味着无论是不是发给自己的信号都会通过接收线路传进来,因此接收操作的第一步就是不管三七二十一把这些信号全都收进来再说(有交换机的情况下情况会不同)。
1)FSC验证
信号的开头是报头,通过报头的波形同步时钟,然后遇到起始帧分界符时开始将后面的信号转换成数字信息。这个操作和发送时是相反的,即PHY(MAU)模块先开始工作,然后再轮到MAC模块。首先,PHY(MAU)模块会将信号转换成通用格式并发送给MAC模块,MAC模块再从头开始将信号转换为数字信息,并存放到缓冲区中。当到达信号的末尾时,还需要检查 FCS。具体来说,就是将从包开头到结尾的所有比特套用到公式中计算出 FCS,然后和包末尾的 FCS 进行对比,正常情况下两者应该是一致的,如果中途受到噪声干扰而导致波形发生紊乱,则两者的值会产生差异,这时这个包就会被当作错误包而被丢弃。
2)MAC验证
如果FCS校验没有问题,接下来就要看一下MAC头部中接收方MAC 地址与网卡在初始化时分配给自己的MAC地址是否一致,以判断这个包是不是发给自己的。我们没必要去接收发给别人的包,因此如果不是自己的包就直接丢弃,如果接收方MAC地址和自己MAC地址一致,则将包放入缓冲区中。到这里,MAC模块的工作就完成了,接下来网卡会通知计算机收到了一个包。通知计算机的操作会使用一个叫作中断的机制。在网卡执行接收包的操作的过程中,计算机并不是一直监控着网卡的活动,而是去继续执行其 他的任务。因此,如果网卡不通知计算机,计算机是不知道包已经收到了 这件事的。网卡驱动也是在计算机中运行的一个程序,因此它也不知道包到达的状态。在这种情况下,我们需要一种机制能够打断计算机正在执行的任务,让计算机注意到网卡中发生的事情,这种机制就是中断。
3)中断
具体来说,中断的工作过程是这样的。首先,网卡向扩展总线中的中断信号线发送信号,该信号线通过计算机中的中断控制器连接到CPU。当产生中断信号时,CPU会暂时挂起正在处理的任务,切换到操作系统中的中断处理程序。然后,中断处理程序会调用网卡驱动,控制网卡执行相应的接收操作。中断是有编号的,网卡在安装的时候就在硬件中设置了中断号,在中断处理程序中则将硬件的中断号和相应的驱动程序绑定。例如,假设网卡的中断号为 11,则在中断处理程序中将中断号11和相应的网卡驱动绑定起来,当网卡发起中断时,就会自动调用网卡驱动了。现在的硬件设备都遵循即插即用的规范自动设置中断号,我们没必要去关心中断号了,在以前需要手动设置中断号的年代,经常发生因为设置了错误的中断号而导致网卡无法正常工作的问题。
4)调用协议,交给应用程序
网卡驱动被中断处理程序调用后,会从网卡的缓冲区中取出收到的包, 并通过 MAC 头部中的以太类型字段判断协议的类型。现在我们在大多数情况下都是使用 TCP/IP 协议,但除了TCP/IP 之外还有很多其他类型的协议,例如NetWare中使用IPX/SPX,以及Mac电脑中使用的AppleTalk 等协议。这些协议都被分配了不同的以太类型,如0080(十六进制)代表IP 协议,网卡驱动就会把这样的包交给TCP/IP协议栈;如果是809B则表示 AppleTalk协议,就把包交给AppleTalk协议栈,以此类推。大家可能会认为向Web服务器发送包之后,后面收到的一定是 Web服务器返回的包,其实并非如此。计算机中同时运行了很多程序,也会同时进行很多通信操作,因此收到的包也有可能是其他应用程序的。不过,即便如此也没问题,网卡不会关心包里的内容,只要按照以太类型将包交给对应的协议栈就可以了。接下来,协议栈会判断这个包应该交给哪个应用程序,并进行相应的处理。

4.收到网络包后,协议如何工作

当web服务器得到一个网络包,协议具体协议栈会进行哪些处理呢?服务器返回的包的以太类型应该是0800,因此网卡驱动会将其交给 TCP/IP协议栈来进行处理。接下来就轮到IP模块先开始工作了,第一步是检查 IP头部,确认格式是否正确。如果格式没有问题,下一步就是查看接收方 IP地址。如果接收网络包的设备是一台Windows客户端计算机,那么服务器返回的包的接收方 IP 地址应该与客户端网卡的地址一致,检查确认之后我们就可以接收这个包了。 如果接收方 IP地址不是自己的地址,那一定是发生了什么错误。客户端计算机不负责对包进行转发,因此不应该收到不是发给自己的包。当发生这样的错误时,IP模块会通过ICMP消息将错误告知发送方。
ICMP 规定了各种类型的消息,如下表所示。

消息类型含义
Echo reply
0
响应 Echo 消息
Destination
unreachable
3
出于某些原因包没有到达目的地而是被丢弃,则通过此消 息通知发送方。