TCP/IP 的链路层是可靠的吗?

如果是可靠的,可靠到什么程度呢?什么异常情况下会变得不可靠? TCP/IP详解(卷1)链路层章节中,给出的链路层帧结构中并无如何分帧的信息,接收端如何…
关注者
127
被浏览
24,987

16 个回答

写完这篇文章,昏昏欲睡,为了提神,上一幅风景画。



问题一:链路可靠性

总体来说,网线比无线可靠,但网线也不是100%可靠,在交换机的入端口错误统计上,CRC Error 一般都是名列前茅,造成CRC Error 的原因有:网卡的软件故障、硬件故障、网线质量、信号干扰。


曾经在数据中心里,接入层的交换机某些入口有1.5%% 的CRC Error,先换网线,情况依然。到最后把服务器重启,CRC Error 消失,过几天故障依然。后来发现这种情况只发生在某个型号,特定版本的服务器上,解决方案是升级软件版本,故障消失。


无线是很不可靠的,可以在电脑上ping 无线路由器,ping 100个包,一般都会丢几个。造成丢失的原因:因为周围有很多工作在同一个频端的无线路由器,互相会干扰,造成无线信号不可用,从而丢弃。


还有一个原因,无线路由器与电脑之间有很多墙,信号衰减很多,再加上干扰,最后变得面目可憎而被抛弃。


问题二:如何分帧?


首先以太网帧是段状结构,不是连续的,帧与帧之间有一个时间间隙(Time Slot)


如上图,这个Inter packet gap 就是间隙,在

10/100/1000

/10000 G的以太网上,这12 byte 对应的是不同的时间间隙,速率越高,时间间隙越小。

问题三: 位填充


IP层做位填充

IP层处理IP包是以32 bit (4 byte)为一个单位,所以IP包的总长度如果不是 4 byte 的整数倍,则需要填充至整数倍,填充内容为0x00(16进制)。


网卡做位填充

以太网帧如果长度小于64 byte(其中包括以太网头部14 byte,帧校验FCS 4 byte),网卡需要将其填充到至少64 byte,满足网卡对最小帧长度的限制。


假设IP层发给网卡的包长只有40 byte, 则网卡需要填充至少 6个 byte 的 0x00(16进制)。


以太网头 + IP + 0x 00 00 00 00 00 00 + FCS


问题四:如何让接收方知道位填充的长度?


IP包头有IP包总长度,那位填充的长度就可以根据这个等式得到:


位填充长度 = 以太网卡提交给IP层的包长 - IP包总长度


其中

以太网卡提交给IP层的包长 = 网卡接收帧 - 以太网帧头 - FCS

在tcp/ip协议栈中,除了传输层的tcp协议,传输层的udp、以及传输层之下的网络层、数据链路层都是“尽最大努力交付”。尽最大努力交付的协议都有校验位,来确认数据传输过程中是否发生了位翻转。 比如在数据链路层是用csc进行校验,在网络层和传输层是利用checksum层进行校验。

什么异常情况下会变得不可靠?

数据链路层处理的是 一个节点通过链路到达另一个节点的问题,也就是一跳,能够影响到这一跳的数据的几个要素有以下几个:

1、物理链路的质量

2、最大传输速率

3、噪声(噪声是不可避免,但是可以通过信噪比降低噪声的影响)

上面这几个要素是影响数据在物理链路上传输的几个重要的因素。重点说,现在链路的质量完全可以让我们放心传输的过程中码元不会失真或者说码元失真的概率非常小)

这里还要结合曼彻斯特编码来讲可能会清楚一点,不过这个是物理层方面的知识。


给出的链路层帧结构中并无如何分帧的信息,接收端如何完成分帧呢?

分帧的过程是有网络适配器完成的,网络适配器有自己的处理器和存储器,能够缓存处理上层(网络层)传下来的数据。

这里补充一下(发现没有写完整)。

数据链路层的三个基本问题,其中一个就是封装成帧,我们知道执行封装的这个动作是由网路适配器来完成。但是我们首先要先确定一个问题,就是接收方的网络适配器接受到一段数据,怎么确定这一段数据是一个完整的帧呢?

这里面会用到帧界定符,即在帧的头部和尾部加上一个特殊的控制字符以识别这个帧。

比如:我们假设帧的数据部分(除了各种协议的头部)里面的信息是ascii文本,我们知道ascii码是7位编码,一共有128个字符,其中99个是打印字符,另外的29个是非打印字符,那么我们就从非打印字符中抽出一个两个字符SOH和EOT作为帧的界定符。

但是这样会出现一个问题,就是 如果数据部分是图片或者视频的编码,那么这些编码中可能会出现SOH和EOT,这样就会导致接收方误判这是一个帧,从而使得数据出错。

那么怎么解决这个问题呢?这个问题就是数据链路层基本问题中的第二个:叫做透明传输。

发送方网络适配器在封装成帧的时候,就会检验在数据部分是否有出现界定符,如果出现就在前面加上一个转义字符,但是我们不能确定数据部分不会出现转义字符呀,怎么办呢?就是在转义字符前再加上一个转义字符,只要接收方接受到帧,只要检测到第一个转义字符,不管接下来的那个是什么,只要把第一个转义字符删掉就ok了。

使用帧界定符最大的好处,就是让接收方知道,比如数据只收到一半,那么接收方就知道这不是一个完整的帧,就会这部分的数据丢弃。

在帧头帧尾添加界定符的方式,在点对点链路中比较常见。

使用界定符来区分帧固然是一种非常好的方式,但是结合到透明传输的问题,你不觉得很复杂么。

所以提出了一种比较简答单的辨别一个帧的方法,就是发送方没法送一个帧,就等待9us(一段时间间隔)再发送下一帧。这样的话,就不用使用界定符来界定,因为接收方连续接收到的数据必然是一个帧,这也是建立在物理链路可靠的基础上(假设每一帧的数据在物理链路上不会丢失)

这样的话,也就不存在透明传输的问题了。这种方式比较常见在广播链路中

当然还有前导码的知识,我这里就不再细讲了。



小于46字节情况下需要填充。

数据链路层 规定 一帧的数据部分最小是46字节---1500字节,数据部分不到46字节的会填充到46个字节。加上18个字节的帧头和帧尾,一共是64字节---1518字节。

填充信息在帧结构中也没有,接收端如何移除填充呢?

这个问题的答案在数据段本身,比如数据段部分是ip协议数据报,那么ip数据报协议头中有协议的长度信息,这个就是接收端移除填充信息的依据。

但是我这里想补充一部分,为什么一帧的最小长度要规定为64字节呢?

这个点在谢希仁的《计算机网络》这本书中并没有针对性的讲解,但是在广播链路随机接入的CSMA/CD有提到一部分,在随机接入的广播链路中,有一个概念叫做碰撞,为了对碰撞的状况进行分析而引入争用期(争用期可以简单的理解为一根线的端到另一端的往返时间)的概念,规定争用期时间是5.12us,如果在传输速率的10Mb/s的链路上,那就5.12us能够发送512位数据,也就是64个字节。

只要在5.12us时间内,局域网没有发生碰撞,那么发送方之后发送的数据就不会发生碰撞。

只要发生碰撞,一定是发送方发送64个字节内,所以规定一帧的最小是64字节。

ps:最后一块是我自己整理完谢希仁《计算机网络》关于数据链路层的一点猜想,有不对希望大家给予指点,谢谢