c/c++linux 深入浅出 TCP/IP 协议栈( 二 )


对于上面的过程,有几个细节问题值得我们思考:
发送者如何知道接收者的MAC地址?
发送者如何知道接收者和自己同属一个子网?
如果接收者和自己不在同一个子网,数据包如何发给对方?
为了解决这些问题,网络层引入了三个协议,分别是IP协议、ARP协议、路由协议 。
【1】IP协议
通过前面的介绍我们知道,MAC地址只与厂商有关,与所处的网络无关,所以无法通过MAC地址来判断两台主机是否属于同一个子网 。
因此,网络层引入了IP协议,制定了一套新地址,使得我们能够区分两台主机是否同属一个网络,这套地址就是网络地址,也就是所谓的IP地址 。
IP地址目前有两个版本,分别是IPv4和IPv6,IPv4是一个32位的地址,常采用4个十进制数字表示 。IP协议将这个32位的地址分为两部分,前面部分代表网络地址,后面部分表示该主机在局域网中的地址 。由于各类地址的分法不尽相同,以C类地址192.168.24.1为例,其中前24位就是网络地址,后8位就是主机地址 。因此,如果两个IP地址在同一个子网内,则网络地址一定相同 。为了判断IP地址中的网络地址,IP协议还引入了子网掩码,IP地址和子网掩码通过按位与运算后就可以得到网络地址 。
【c/c++linux 深入浅出 TCP/IP 协议栈】由于发送者和接收者的IP地址是已知的(应用层的协议会传入),因此我们只要通过子网掩码对两个IP地址进行AND运算后就能够判断双方是否在同一个子网了 。
【2】ARP协议
即地址解析协议,是根据IP地址获取MAC地址的一个网络层协议 。其工作原理如下:
ARP首先会发起一个请求数据包,数据包的首部包含了目标主机的IP地址,然后这个数据包会在链路层进行再次包装,生成以太网数据包,最终由以太网广播给子网内的所有主机,每一台主机都会接收到这个数据包,并取出标头里的IP地址,然后和自己的IP地址进行比较,如果相同就返回自己的MAC地址,如果不同就丢弃该数据包 。ARP接收返回消息,以此确定目标机的MAC地址;与此同时,ARP还会将返回的MAC地址与对应的IP地址存入本机ARP缓存中并保留一定时间,下次请求时直接查询ARP缓存以节约资源 。cmd输入 arp -a 就可以查询本机缓存的ARP数据 。
【3】路由协议
通过ARP协议的工作原理可以发现,ARP的MAC寻址还是局限在同一个子网中,因此网络层引入了路由协议,首先通过IP协议来判断两台主机是否在同一个子网中,如果在同一个子网,就通过ARP协议查询对应的MAC地址,然后以广播的形式向该子网内的主机发送数据包;如果不在同一个子网,以太网会将该数据包转发给本子网的网关进行路由 。网关是互联网上子网与子网之间的桥梁,所以网关会进行多次转发,最终将该数据包转发到目标IP所在的子网中,然后再通过ARP获取目标机MAC,最终也是通过广播形式将数据包发送给接收方 。
而完成这个路由协议的物理设备就是路由器,在错综复杂的网络世界里,路由器扮演者交通枢纽的角色,它会根据信道情况,选择并设定路由,以最佳路径来转发数据包 。
【4】IP数据包
在网络层被包装的数据包就叫IP数据包,IPv4数据包的结构如下图所示:

c/c++linux 深入浅出 TCP/IP 协议栈

文章插图
 
IP数据包由首部和数据两部分组成,首部长度为20个字节,主要包含了目标IP地址和源IP地址,目标IP地址是网关路由的线索和依据;数据部分的最大长度为65515字节,理论上一个IP数据包的总长度可以达到65535个字节,而以太网数据包的最大长度是1500个字符,如果超过这个大小,就需要对IP数据包进行分割,分成多帧发送 。
所以,网络层的主要工作是定义网络地址,区分网段,子网内MAC寻址,对于不同子网的数据包进行路由 。
3、传输层
链路层定义了主机的身份,即MAC地址,而网络层定义了IP地址,明确了主机所在的网段,有了这两个地址,数据包就从可以从一个主机发送到另一台主机 。但实际上数据包是从一个主机的某个应用程序发出,然后由对方主机的应用程序接收 。而每台电脑都有可能同时运行着很多个应用程序,所以当数据包被发送到主机上以后,是无法确定哪个应用程序要接收这个包 。
因此传输层引入了UDP协议来解决这个问题,为了给每个应用程序标识身份,UDP协议定义了端口,同一个主机上的每个应用程序都需要指定唯一的端口号,并且规定网络中传输的数据包必须加上端口信息 。这样,当数据包到达主机以后,就可以根据端口号找到对应的应用程序了 。UDP定义的数据包就叫做UDP数据包,结构如下所示:


推荐阅读