接上一篇:【网络面试必问(5)】网络收发数据及断开服务器(四次挥手)
在之前的博客中,我们提到过,网络传输的报文是有真实的数据包和一些头部组成的,目前我们了解的头部就有TCP头、IP头、MAC头,而且这三个头部信息都是在应用程序委托给协议栈之后,被写入的相关信息,这些头部都是跟网络包的转发和传递有关系的。前面我们学习了TCP协议对网络包的拆分、重发、三次握手四次挥手等机制,这一篇博客看一下,在IP协议中,如何借助于IP头部和MAC头部实现对网络报文转发的。
1. 网络包添加头部信息
在IP协议中,包转发的起点是在网络包的头部添加IP头部和MAC头部。这里先了解这两个概念,IP头部是跟IP地址相关的,也就是通过IP地址要知道最终应该把包发送给这个IP对应的服务器,这个目的地的IP地址自始至终不会发生变化。MAC头部则是跟以太网协议相关,他记录的是网络线路中最近的、将要到达的路由的MAC地址,随着包在路由器之间相互传递,这个MAC地址会被修改为将要到达的下一个MAC地址。
1.1 IP头部
IP头部,顾名思义记录的就是跟收发双方IP地址相关的控制信息,这一动作是由IP模块添加到网络包头部的,这里面最重要的就是IP地址,这个IP地址就是TCP模块告知给IP模块的,还记得我们在TCP连接阶段,调用Socket库的时候入参的IP地址吗?connect(<套接字描述符>, <服务器IP地址>, <服务器端口号>, ...)
,IP协议只会负责将包发送给此IP对应的服务器,至于中间的丢包、重试统统不管,这是TCP模块该做的事情。我们看下IP头部的格式:
这里面除了接收方IP地址之外,还有发送方IP地址,发送方地址这里会涉及到一个知识点,对于大部分计算机来说,一台计算机装有一个网卡,没问题,这个IP地址就是这块网卡上的,但是对于有多个网卡的性能优异的计算机,就代表这有多个IP地址,那么发送方的IP地址应该写哪个呢,也即是应该通过哪块网卡将消息发送出去呢?
这里就需要通过IP路由表
去确定应该使用那一块网卡,我们来使用一个命令``route print`可以看到这张位于计算机上的路由表。
举个例子,现在我们要向IP地址未192.168.1.233
的服务器上发消息,根据子网信息192.168.1.x
就可以匹配到第6行192.168.1.0
的这一行。我们看下这几列分别表示什么意思:
- destination 目标的子网地址
- netmask 子网掩码,和目标IP地址可以确定子网地址
- gateway 网关,这里指的是路由器的IP地址
- interface 接口,这里指的就是我们要找到网卡ip地址。
通过路由表,我们确定了第6行的interface
的10.10.1.16
就是我们要使用的网卡,这样,消息就知道要在哪里发送出去了。
1.2 MAC头部
在IP头部添加完成后,还需要再IP头部前面添加MAC头部,MAC头部是以太网使用的头部,包含发送方和接收方的MAC地址信息。
我们首先来看下MAC头包含的完整信息。
这里面,首先看以太类型,和IP头部的协议号类似,表明当前是那种协议的网络包,我们使用IP协议,就是16进制的 0800。另一个信息是发送方的MAC地址,其实也好找,前面我们已经确定好了是由哪块网卡发送网络消息了,因此读取这块网卡的MAC地址就可以了。MAC地址是厂家在生产的时候烧录在ROM里面的,一般不会变动,长度48个bit。
然后就是发送方的MAC地址了,从发送开始,我们无从得知接收方的MAC地址是什么,也就是应该把消息发送到哪一块网卡。这里就需要ARP协议和路由表了,在首次发送网络包的时候,ARP协议会通过广播的形式,向子网中的所有网络设备发送消息,发送请求询问当前接收方IP地址由哪块网卡做转发。如果子网中确实有这样一块网卡转发此IP的网络包,就会回复消息,这样接收方的MAC地址就确定了,其实就确定了应该把网络包发送到哪个网卡上。
需要注意的是,并不是每次查询MAC地址都需要发送广播请求,因为ARP缓存会把前一次查询的结果缓存下来,几分钟会过期,所以这里可能会有子网设置网络信息变动,导致实际情况和ARP缓存不一致的情况。
经过上述处理,发送方和接收方的MAC地址都知道了,就可以发送包含了MAC头部和IP头部的网络包了。在现实生活中,我们可以把IP头部信息比作快递中填写的收件人的地址,是不会变的,而MAC地址是邮递过程中,作为中转站的不同快递站点,是可以发生变化的,最终目的就是为了找到收件人的地址。
2. 将网络包转换成光/电信号发送到接收方
网络包是存放在内存中的二进制数据,并没有办法直接发送给对方,要想通过网线或者光纤发送给对方,还需要转换成光或者电信号发送出去。
负责这一操作的就是网卡,网卡是硬件,本身也没法独立完成这个转换,因此还需要网卡的驱动程序来控制网卡完成这个转换。在操作系统启动之初,网卡驱动程序会对网卡进行初始化,这里会包含错误检查,初始这是、mac地址设置等等,这个MAC地址是全世界独一无二的。
2.1 MAC模块添加报头、起始帧分界符和帧校验序列
网卡驱动程序从IP模块获取到网络包信息之后,会将其复制到网卡的缓存中,然后调用MAC模块,完成发送包的命令。那么MAC模块在这期间,完成了哪些工作呢?
首先,mac模块读取缓冲区中的数据,然后在网络包的起始位置添加上报头
和起始帧分界符(SFD)
,在末尾添加上用于检测错误的帧校验序列
。
- 报头:用来测定读取报文的时机,报头的0和1变化频率是和时钟信号变化频率同步的,因此接受方通过一段时间对报头的0和1变化观察,就能找到固定的变化周期,确定时钟信号的发送的频率。
- 起始帧分界符(SFD):在经过一段报头的数据之后,会有一段长度为8个比特的起始帧分界符,起始帧分界符的末尾比特排列有少许的变化,用以告诉读取的一方,报头将要结束, 接下来要读取的就是正式的数据包。
- 帧校验序列(FCS):是在包末尾的、长度为32比特的序列,是通过一个公式计算出从包头到包尾的内容,用以接收方在接收到网络包之后对数据包进行校验,避免中间发生数据错误。
2.2 发送网络包
当网络包封装好之后,就会向以太网中发送信号,MAC模块就会从包头开始将数字信息按照每个比特转换成电信号,然后由信号收发模块发送出去,这里将数字信息转换成电信号的速率就是我们常说的网络传输速率,例如每秒把10Mbit的数字信息转换成电信号发送出去,这里的网速就是10Mbit。