你的数据是如何送到另一台计算机上的(一)
前言
你是否想过为什么你的数据可以从你的计算机上分毫不差的传送到另一台计算机上呢?你发送绝大多数数据的时候,都不知道接受数据的人在哪里,那么这个网络又该如何知道那一台计算机是谁,在哪里,该经由哪些线路才能到达?这一系列文章就是要探讨这个问题。
设想一下,假如世界上只有两台计算机,你的工作是让他们互相通信,你会怎么做?
两台电脑之间的通信
首先,你得在两台计算机上安装一个带有插孔的设备,然后找条电线把他们两个连接起来,这样信息就可以通过电线来传送了,这个设备就叫做网卡 Network Interface Contorller。随着互联网的发展,已经几乎没有计算机不联网了,所以独立的网卡硬件已经很少见了,因此现在的网卡大多直接集成在主板上
主板上的REALTEK网络芯片
那么计算机中的数据又是如何经过电线来传输的?
我们知道,计算机中的信息都是由二进制表示的,构成二进制的每一个1
和0
称为一个比特(bit)。我们可以规定做下面几个规定:
-
5V
电压表示1
,0V
电压表示0
(基本上就是电线通电代表1
,不通电代表0
)。同时我们称5V
为高电平,0V
为低电平。 - 双方以每秒100次的频率(这个频率也称为“Clock”,1s/100=0.01s称为一个周期)来发送和接收消息。也就是说,以
0.01
秒为周期,由接收方去检测电线的电压,根据电压是5V
还是0V
来判断收到的是1
还是0
。
那为何不是6V
和3V
?电信号在线缆中传输时,为应对其他电磁场的干扰带来的失真和衰减,收到信号的时候还需要经过一些放大处理,如果采用的是6V
和3V
这样的信号,经过一次衰减和放大后可能会产生混淆。因此5V
和0V
的设计有更强的抗干扰能力。
事实上,网络的传输能力和干扰之间的关系是密不可分的,这个我们在后面会稍微讲一下。
具体来说,如果发送方想要发送一个1
或0
,他需要提前半个周期(也就是0.005
秒)调整电路的电压,然后供接收方在每个周期开始时读取。之所以要提前半个周期去调整电压,是为了防止接收方读取了到上一个周期的过时数据。
因此,假如A要发送101001
这段信息给B,电线中的电压看起来就会像是这样子:
但是这个世界并没有这么单纯,我们规定了两台计算机收发信息的clock,但是我们并不能确保他们的clock一定是同步的!
时钟不同步很容易发生,而且后果很严重——如果B比A晚开机0.006
秒,他们的时钟就会错开0.6
个周期(我们也可以说他们错开了0.6个相位),此时去读取数据结果会完全不同,如图
这个由于时钟相位不同导致数据错误的问题称为 Clock Slip。
1.独立时钟信号?
既然从物理上解决时钟同步问题是不可行的(难道要在每个电脑中集成一个原子钟吗),我们可否再连接第二根线来发送时钟信号呢?这是可行的。
在时钟信号中,电压也会在0V
和5V
之间规律的变化,接收方只有到时钟信号中的电压产生了0V->5V的变化时,才去数据信号中读取数据。采用这种方式后,双方也就无需预先规定一个时钟了,接收方完全按照发送方发来的时钟信号即可。如图:
这个做法看起来完美,但是如何保证时钟信号和数据信号严格同步其实并不是一件容易的事情。比如说,两根电线长度有微小的差异,线材电阻不同,或是受到了不一样的电磁干扰,都有可能导致他们的信号相位差生差异,产生 Clock Flip。
尽管在100次/s这个频率下问题不明显,但是随着时钟频率的提升,出问题的可能性会逐步提高,因为一点微小的时差都会造成很大的数据错误。
2.更加聪明的办法 —— 曼彻斯特编码
曼彻斯特编码是一种将时钟信号结合到了数据信号中的优雅设计,他的要义是,使用电压的变化而非高低来表达信息。因为变化本身是一个带有时间属性的事情,所以这个信号同时也可以携带时序信息。
具体来说,它用5V->0V的跳变代表0,用0V->5V的跳变代表1,因此时序信号看起来是这样的:
曼彻斯特编码的时序图那么,这种编码是如何解决时钟相位同步问题的呢?
首先,我们依然需要规定一个时钟频率,当接收方收到第一次的电压变化时,它会立刻将时钟相位重置,以此来确保接下来的时序中它和发送方的相位是一致的。
在上图中,接收方首先接收到一个5V-0V
的变化,代表0
,然后到下一个周期开始时,刚好又接收到一个0V-5V
的变化,于是它接收到了1
,紧跟着又接收了一个0
。
此时问题来了,现在电压已经在0V,下次又要接收5V-0V
的变化才能代表0
的话,如果想要发送一个0
,岂不是要先把电压变成5V才行吗?那么这个0V~5V
的变化,难道不会被接收方识别为一个1
吗?
不用担心,曼彻斯特编码还是规定了频率的,因此接收方知道周期是多少(我们要解决的只是相位同步的问题,记得吗?),当一个电压变化发生在1/2周期的时候,接收方知道这是为了准备下一次数据传输,所以它会直接忽略这个变化。
说到这里,聪明的你可能发现了这个设计依然有问题。电压的默认状态是0V
,要是第一个bit是0
,在进行5V-0V
的变化之前,肯定要先进行一次0V-5V
的变化,那么按照上面的逻辑,这个0V-5V
的变化就会直接被接收方认为是有效的,并且重置相位,导致今后的数据全部错误了,这该如何处理?
3. 更进一步 —— 真实世界中的曼彻斯特编码
如果你刚才点进去过曼彻斯特编码的维基百科页面,可能你已经发现了,里面的示意图和我们上面的不太一样,是长这样的: 第三条线是曼彻斯特编码,第四条是翻转后的曼彻斯特编码上面的图和我们之前的图不一样,看起来有三种电压,在初始位置是一个非高也非低的电压。这是因为在实际使用中,网线中流通的是交流电而非直流电,因此,我们可以用5V
和-5V
来区分1
和0
,而非原来的5V
和0V
。这使得我们可以用0V
来作为初始状态,从而解决上面提到的问题。
既然问题是 “无法区分第一次电压变化是在表示数据还是为下一次表示数据做准备” ,那么以如果0V
为初始状态,第一次改变肯定是0V
-5V
或0V
--5V
,而非-5V
-5V
或5V
--5V
,即不代表1
也不代表0
,所以会被接收方直接忽略。
上面这张图片是一个真实的例子(把一个示波器直接接在了网线上),从图上我们可以看出这么几件事情:
- 由比例尺可以看出,纵轴的比例尺是一格
500mV
。信号在的振幅是上下两格,因此是使用1V
代表1
,-1V
代表0
。横轴的比例尺是一格,100ns
(100纳秒,即10-7秒),每次有效的电压变化都发生在网格线上,因此一个周期是100ns,1秒可以传输107个bit,即10,000,000个bit,所以这是一个10Mb/s的网络。 - 电压的变化在真实环境中是一个正弦波,而不是理论上的方波
- 传输的数据读取出来可以组合为两个字节(byte)
11010010
和10000010
。但是在以太网中这个数据在解码时需要进行一次颠倒操作(我也不知道为啥),于是可以变成01001011
和01000001
,代表75
和65
,在ASCII表中就代表K
和A
。
以太网
上面我们已经两次提到了以太网(Ethernet)了,那么以太网是什么呢?
Wikipedia中是这么说的:
以太网(英语:Ethernet)是一种计算机局域网技术。IEEE组织的IEEE 802.3标准制定了以太网的技术标准,它规定了包括物理层的连线、电子信号和介质访问层协议的内容。以太网是目前应用最普遍的局域网技术,取代了其他局域网标准如令牌环、FDDI和ARCNET。
事实上,两台计算机组成的网络,可以看作一个最简单的局域网。为了在局域网中传输数据,我们需要定义清楚更多的细节,比如数据如何分割?一次传输多少数据?怎么提高通信效率?这些信息以太网标准都给出了规定。
以太网中的数据分割
首先,8个bit组成一个字节,它是信息的最小单位。
那么,第一个字节是从哪里开始计算呢?
前文中我们提到,曼彻斯特编码方式中,初始状态电压为0,电压什么时候开始变化,什么时候就是第一个bit。这个初始为0电压的状态,在以太网中称为IFG(Interframe Gap)。为了防止因为干扰造成电压短暂归0,以太网规定IFG必须持续至少96个周期,也就是12(12*8=96)个字节,因为IFG如果持续时间不够长,那么是不足以达到抗干扰的要求。
在IFG之后,为了保护数据本身,并给接收方一个同步时钟的机会,以太网还引入了一段称为Symcword(也叫Premble)的信息,这是一段持续56个周期的10
序列,并在序列最后加上一段10101011
最为Syncword的终止信号(一共64个周期,也就是8字节)。由于这个终止信号同时也代表着真正的数据开始了,所以他叫做Start of frame delimiter。
使用了Syncword之后,接收方可以去匹配发送方的时钟频率,因此以太网就可以称为一个“自时钟”(Self-Clock)的标准,也就是说并不需要像我们之前假设的那样双方规定好时钟屏率,完全可以在发送信息的时候动态协商。
然而,就算采用了IFG来避免一次传输开始的时机不会弄错,我们仍然没法避免信号在传输的过程中产生干扰或故障导致信息的错误。因此以太网标准中还规定了一些验证的信息正确性的方式(类似下载文件时的校验码)比如CRC。但是由于效验方式必须要兼顾效率,你只能知道一段数据有没有错误,而不知道哪里有错误,因此,一次传输的数据还不能太长,否则一旦错误就会有很多数据需要重新传送。
那么,具体一段数据应该有多长,效验具体又是如何做的呢?下一节我们会在我们的脑补网络中加入更多台电脑和交换机,组成一个完整的局域网后,再来讲解以太网中一次通讯的最小单位“数据帧”是如何构成的。
双绞线和双工
说了半天信号,我们最后来简单说一说线。
现在的网线其实大部分都是使用的双绞线,我们说的5类线6类线也都是双绞线的标准。一条双绞线大概是这个样子的:
可以看到,一条双绞线中,有数对(通常是4对)相互缠绕的铜芯线组成。之所以是这样的结构,是因为在两根互相缠绕的导线中通上相等并相反的信号(equal and opposite signals)时,每一根导线在传输中辐射出来的电波会被另一根线上发出的电波抵消,有效降低信号干扰的程度。
,想看原理的同学可以移步这篇文章,我并看不懂。
那么有四条对线又有什么用呢?其实以太网只用到了其中两对,一对用来发送信息,一对用来接收信息,这样两台计算机直接就可以同时马力全开的发送和接收信息,而不会互相影响或者互相等待。因此,我们说以太网是双工的。
留个思考题:现在你是否知道为什么不同的线传输信号的速率不一样了呢?
大部分知识来自 Ben Eater 的系列视频:《Networking tutorial》,主要是以下几节(部分图片也截图自此视频):