三十天学不会TCP,UDP/IP编程--MAC地址和数据链路层

时间:2023-12-27 19:53:13

这篇文章主要是来做(da)推(guang)介(gao)的!由于这两年接触到了比较多的这方面的知识,不想忘了,我决定把他们记录下来,所以决定在GitBook用半年时间上面写下来,这是目前写的一节,后面会不断更新,主要是在写完之前欢迎各位给出指正的意见。最最重要的,地址在这里:https://www.gitbook.com/book/rogerzhu/-tcp-udp-ip/,或者在gitbook上搜索“三十天学不会TCP,UDP/IP编程”。

MAC 地址

到了数据链路层,就开始有了数据的整合管理了。如何标识发送数据的两个端点,应该是网络的第一个问题,不能说连对方的地址都不知道你就敢寄信(不过也有例外的,就是广播,在后面再详述)。可以看到在物理层只有一个接口的物理信息,一般是标识厂家的ID和批次等等,先不说这些东西很大概率会是重复,而且这玩意儿又是不定长字母加不定长数字的也不好管理,所以产生一种便于统一管理且不会重复的唯一标识符就很必要了。于是ISO,IEEE等等机构就定义了这么一个玩意儿,称之为MAC地址,全名Media Access Control Address,这个MAC比现在最流行的mac要早很多年。

一个MAC地址有48位,一般在表示的时候分为6个组,每个组用两个16进制的数字组成。前24位是由IEEE决定如何分配,一般是需要的公司向IEEE申请,基本上前面的24位就可以保证唯一性了,因为IEEE会进行管理和分配,后面24位由生产厂家自行决定。一个网卡只能有一个MAC地址,如果需要在一个设备上需要多个MAC地址,那么就需要多个网卡。

关于MAC地址还有一个重要的概念是单播MAC地址,广播MAC地址,多播MAC地址的概念,我想放在网络层描述比较自然,不过可以简单的这样理解,单播嘛就是和一个定点通信,广播就是大声的喧哗,小喇叭看看谁会回复,多播就是在这个组内每个人都能看到别人说话,但是组外就看不到了。

在windows上,使用ipconfg /all就可以看到你的网卡MAC地址,在linux上,使用ifconfig就可以查看。这里我觉得,从命令的名字上,linux的更接近于原意,interface config,毕竟MAC地址不能说是ip,这些信息应该属于一个接口信息。

帧格式

还是结合那个SMB包,让我们展开第二层看看具体有什么。

三十天学不会TCP,UDP/IP编程--MAC地址和数据链路层

三十天学不会TCP,UDP/IP编程--MAC地址和数据链路层

在这个包的第一行最前面是Ethernet II,Ethernet翻译成中文就是以太网,以太这个词是亚里士多德设想的一种物质,在当时用于描述摸不到看不着却又能真实感受到存在的东西,当然,后来科学证明了没有这种东西,但是我觉得用在这里形容网络真是再恰当不过了。再说回Ethernet II,这是链路层的一种帧格式,另外一种是IEEE802.3。这种编号方式的规范本身没什么好记忆的,事实上IEEE802定义了一系列网络通信的帧格式,其中IEEE802.11就是和现在每个人都息息相关的无线网标准了,IEEE802.11ac不也是苹果的卖点之一嘛。

那么Ethernet II 的帧格式到底是什么样的呢?我从wiki上复制了一张组成部分图,可以很清晰的看到,主要分为三大部分五小部分,其中MAC header包含了源MAC地址和目的MAC地址,Ether Type是标识了data的类型,从上面的抓包截图上看到了一个Type:IPv4(0x0800),就是填在这个字段的。再往下就是Data,也就是真实的数据包,比如IP数据等等。后面是一个CRC检验码,目的是为了检查这个包有没有出错。如果出错,就会丢弃这个包。其算法一两句话很难描述清楚,在你完全不知道的情况下,可以认为他是一个可以标识出一段二进制数有没有被篡改的方法。这个CRC码在这个帧里面是4个字节的,所以用的是CRC32算法。

三十天学不会TCP,UDP/IP编程--MAC地址和数据链路层

三十天学不会TCP,UDP/IP编程--MAC地址和数据链路层

下面来看一看我们这个包里面的MAC header如何和这个对应的,对比第一个图我们可以很兴奋的看到,前6字节是dest mac,接着6个是src mac,然后就是0800的类型标识了,果然诚不欺我。

三十天学不会TCP,UDP/IP编程--MAC地址和数据链路层

三十天学不会TCP,UDP/IP编程--MAC地址和数据链路层

那么另外一种IEEE802.3到底是什么样子的呢?其实大部分和具体展开介绍的差不多,但是这种格式多了在链路层的控制,这些控制字段会占用掉一些Data字段的空间,所以会牺牲运送的数的大小。一般在交换机之间会采用这种帧格式,有兴趣的话其实可以了解一下。

Ethernet II有个最小长度和最大长度,其实任何一个帧格式都会定义最小长度和最大长度的,原因是为什么呢?这个我放在这一节的最后再介绍好了。从图一中还可以验证我上面不是扯淡的就是两个MAC地址前24位都显示的是VMware,这就是IEEE分配给VMware的,wireshark会显示友好的名称,接下来的24位就厂商编码的了。那么图中显示的LG bit和IG bit又是什么意思呢?LG 为0表示这是一个厂家默认的MAC地址,如果是1那么就是用户自己设置的MAC地址,你会说MAC地址不是出厂前设置好的吗?还能改呢,其实如果有特殊的方法,确实能改,我以前就通过BootLoader改过MAC地址。那么IG bit是什么意思呢?IG bit为0表示这是一个单播地址,至于什么是单播,组播和广播,到网络层的时候再详尽说明会比较自然一点。

如果你用wireshark抓包的话,你会发现,不会有最后四个检验和字段的,这是为什么呢?因为硬件在传上来的时候回丢弃这个字段,所以wireshark也不能抓到这个包,但是既然wireshark显示了这个包,说明这个CRC肯定是正确的。因为不正确的已经被网卡驱动丢弃了,更不会抓到这个包了。

为什么会有长度的限制?

上面提到过,Ethernet 的帧会有长度限制,既有最小限制,也有最大限制。最大限制简单的理解就是,万事万物都有个最大的能承载的极限,限制帧的最大长度是为了避免一台设备长时间占用信道。在遥远的时期,只能有这么长的上限,但是现在普遍都可以通过配置来使得最大长度大于1518个字节了。我第一看到这个长度限制的时候,我最疑惑的是为什么还有最小长度限制,下面我尽力阐述一下我所理解的这个限制的由来。

首先要说的一个概念叫CSMA/CD,中文是载波多路复用/冲突检测,这个名词看完之后更疑惑了。但是这个概念很简单,在很多并发编程里面都用到了这个简单而又有效的技术。因为网络是共享的,所有的主机端在发送自己的数据前第一件事是检测下线路上是不是空闲的,就是说路有没有被占用,路上有没有车。如果有车还开车上去,那么必然就出事故了。网卡检测到线路上有数据,这个时候不能发车怎么办呢,这里设计者们采用了一个最原始却最有效的办法——等一会儿再发,回头再看看这个技术的名词,是不是有些理解了?

这样考虑上面说的CSMA/CD一个极限情况,如果主机发送的帧很小,而两台冲突主机相距很远。如果在一个主机发送的帧恰好要刚刚到达对方的时候,对方这个时候发送一个帧,因为这个时候对方检测信道是空闲的,他可以发送数据。而这时发送方的数据到达了,对方开始发送帧,一下子就碰撞了。这时候对方会发出一个冲突信号企图告诉发送方方有冲突了,但偏偏发送方的帧已经发送完毕,那么发送方将检测不到冲突而误认为已发送成功。由于电信号毕竟不能突破基本物理定律,传播是有时延的,因此检测冲突也需要一定的时间。这也是为什么必须有个最小帧长的限制。

那么最小限制怎么算出来的呢,这是因为在标准中,10Mbps的以太网采用中继器进行连接的时候,最大长度是2500米,最多就只能经过4个中继器。因此规定对10Mbps以太网一帧的最小发送时间为51.2微秒。这段时间所能传输的数据为512位,因此也称该时间为512位时。这个时间定义为以太网时隙,或冲突时槽。512位=64字节,这就是以太网帧最小64字节的原因。

也许这么说可能还是过于抽象了,简单的理解可以认为最大长度限制是避免一个帧占用信道太长时间导致别的主机没有机会发送,最小的长度限制是避免了由于传播实时延的问题,冲突检测无法成功。

交换机

我遇到太多人分不清交换机和路由器的区别,其实我觉得记住一句话就好,交换机是一种工作在数据链路层的设备,可以识别MAC地址但是不知道IP地址的。

三十天学不会TCP,UDP/IP编程