包收发操作的起点是TCP模块委托IP模块发送包的操作。这个委托的过程就是TCP模块在数据块的前面加上TCP头部,然后整个传递给IP模块,这部分就是网络包的内容。与此同时,TCP模块还需要指定通信对象的IP地址,也就是“将什么内容发给谁”。
收到委托后,IP模块将包的内容当作一整块数据,在前面加上包含控制信息的头部。IP模块会添加IP头部和MAC头部这。IP头部中包含IP协议规定的、根据IP地址将包发往目的地所需的控制信息;MAC头部包含通过以太网的局域网将包传输至最近的路由器所需的控制信息。
凡是局域网所使用的头部都叫MAC头部,但其内容根据局域网的类型有所不同。除局域网之外的其他通信技术,还有不同名称的各种头部,但它们只是名字不叫MAC头部,承担的作用和MAC头部是相同的。
IP模块接受TCP模块的委托负责包的收发工作,它会生成IP头部并附加在TCP头部前面。IP头部中最重要的内容是IP地址,它表示这个包应该发到哪里去。这个地址是由TCP模块告知的,而TCP又是在执行连接操作时从应用程序那里获得这个地址的,因此这个地址的最初来源就是应用程序。
一般的客户端计算机上只有一块网卡,这种情况下我们认为这个IP地址是计算机的IP地址,但如果计算机上有多个网卡,IP地址不知道通过哪个网卡把包消息发出去,不知道应该把包发往哪个路由器,因此只要确定了目标路由器,也就确定了使用哪块网卡,也就确定了发送方的IP地址。
首先,对套接字中记录的目的地IP地址与路由表左侧的Network Destination栏进行比较,找到对应的一行。
例如,TCP模块告知的目标IP地址为192.168.1.21,那么就对应图中的第6行,因为它和192.168.1的部分相匹配。如果目标IP地址为10.10.1.166,那么就和第3行10.10.1的部分相匹配。以此类推,我们需要找到与IP地址左边部分相匹配的条目。
生成了IP头部之后,接下来IP模块还需要在IP头部的前面加上MAC头部。IP头部中的接收方IP地址表示网络包的目的地,通过这个地址我们就可以判断要将包发到哪里,但在以太网的世界中,TCP/IP的这个思路是行不通的。以太网在判断网络包目的地时和TCP/IP的方式不同,因此必须采用相匹配的方式才能在以太网中将包发往目的地,而MAC头部就是干这个用的。
IP模块在生成IP头部之后,会在它前面再加上MAC头部。MAC头部是以太网使用的头部,它包含了接收方和发送方的MAC地址等信息。
发送方MAC地址,填写网卡本身的MAC地址。MAC地址是在网卡生产时写入ROM里的,只要将这个值读取出来写入MAC头部就可以了。对于多块网卡的情况,请大家回想一下设置发送方IP地址的方法。设置发送方IP地址时,我们已经判断从哪块网卡发送这个包,那么现在只要将这块网卡对应的MAC地址填进去就好了。
拿到本端MAC后,对方的MAC地址怎么拿到呢?
大家都知道ARP。通过ARP查询目标路由器的MAC地址。
在以太网中,有一种叫作广播的方法,可以把包发给连接在同一以太网中的所有设备。ARP利用广播对所有设备提问:“××这个IP地址是谁的?请把你的MAC地址告诉我。”然后就会有人回答:“这个IP地址是我的,我的MAC地址是××××。
如果对方和自己处于同一个子网中,那么通过上面的操作可以得到对方的MAC地址。然后,我们将这个MAC地址写入MAC头部,MAC头部就完成了。
如果每次发送包都要这样查询一次,网络中就会增加很多ARP包,有一块叫作ARP缓存的内存空间会暂存这些信息。
在发送包时,先查询一下ARP缓存,如果其中已经保存了对方的MAC地址,就不需要发送ARP查询,直接使用ARP缓存中的地址,而当ARP缓存中不存在对方MAC地址时,则发送ARP查询。
有了ARP缓存,可以减少ARP包的数量,但如果总是使用ARP缓存中保存的地址也会产生问题。例如当IP地址发生变化时,ARP缓存的内容就会和现实发生差异。为了防止这种问题的发生,ARP缓存中的值在经过一段时间后会被删除,一般这个时间在几分钟左右。这个删除的操作非常简单粗暴,不管ARP缓存中的内容是否有效,只要经过几分钟就全部删掉,这样就不会出问题了。
将MAC头部加在IP头部的前面,整个包就完成了。到这里为止,整个打包的工作是由IP模块负责的。
有人认为,MAC头部是以太网需要的内容,并不属于IP的职责范围,但从现实来看,让IP负责整个打包工作是有利的。如果在交给网卡之前,IP模块能够完成整个打包工作,那么网卡只要将打好的包发送出去就可以了。对于除IP以外的其他类型的包也是一样,如果在交给网卡之前完成打包,那么对于网卡来说,发送的操作和发送IP包是完全相同的。这样一来,同一块网卡就可以支持各种类型的包。
本文摘取自周自恒翻译的户根勤编写的《网络是怎样连接的》
网友评论