pc28.am神测网:网络七层协商之数据链路层,互联
分类:pc28.am神测网

原文地址:https://learn-linux.readthedocs.io

QQ交流群:Linux网络编程,群号:183196643

欢迎关注我们的公众号:小菜学编程 (coding-fan)

我们以一个非常简单的例子开始:

一.硬件介绍

前一节讨论了一个理想化模型——两服务器通讯。 现在,我们把问题进一步拓展一下:多台机器如何实现两两通讯?

我们以一个非常简单的例子开始:

pc28.am神测网 1两服务器通讯问题

RH是相对湿度,是用零点温度来定义的,一般,RH在45%~65%之间最为合适。

原文地址:https://learn-linux.readthedocs.io
QQ交流群:Linux网络编程,群号:183196643
欢迎关注我们的公众号:小菜学编程 (coding-fan)

两服务器通讯问题

pc28.am神测网 2

如上图,有两台服务器,分别是 Server 1 和 Server 2 。 我们先做一个假设:计算机网络现在还没有被发明出来, 作为计算机科学家的你,想在这两台服务器间传递数据,怎么办?

这时,你可能会想到,用一根电缆把两台服务器连接起来:

pc28.am神测网 3

物理课大家都学过,电线可以分为 低电平 和 高电平 。 电平可以高低变化,这样不就可以传递信息了么: Server 1 控制电缆电平的高低, Server 2 检测电平的高低,这样就实现了 Server 1 往 Server 2 发送数据啦!

更进一步,可以将高低电平抽象成数学语言:我们用低电平表示 0 ,高电平表示 1 ,这样就得到一个理想化的信道:

pc28.am神测网 4

通过信道,双方可以传递一些 01 比特流。 例子中,我们传输的比特流是 1111010101... (从右往左看)。 比特流可以编码任意信息: 比如,我们用 1111 表示告诉对方本地开机了,用 0000 告诉对方本地准备关机了。

到目前为止,我们是不是万事具备了呢? 一个比特流信道成为现实?——理论上是这样子的。 但是,现实世界往往要比理想化的模型复杂一些。

如上图,有两台服务器,分别是 Server 1Server 2 。 我们先做一个假设:计算机网络现在还没有被发明出来, 作为计算机科学家的你,想在这两台服务器间传递数据,怎么办?

pc28.am神测网 5

多服务器通讯问题

注解

为了简化接下来的讨论,我们站在物理层的基础上,所有数据发送省略控制比特 10100101

下面,以三台服务器为例:

pc28.am神测网 6

图中,有 3 台服务器,名字分别是: antbee 以及 cicada 。 为了通讯,我们设想三者均连接至一根共用导线,每台服务器都可以改变导线电平,也可以检测导线电平。 进一步假设,在硬件层面,多机器冲突仲裁机制已经实现并且可用。 这样,是否解决了多服务器通讯问题?

发送控制

pc28.am神测网 7

首先,如上图,信道是无穷无尽的。 因为,信道状态要么为 0 ,要么为 1 ,没有一种表示空闲的特殊状态。

pc28.am神测网 8

举个例子,如上图, Server 1 向 Server 2 发送比特序列 101101001101 (从右往左读)。 最后一个比特是 1 ,对应的电平是高电平。 发送完毕后,由于没有没有其他地方改变电缆的电平,所以还是维持高电平状态。 也就是说,信道看起来还是按照既定节拍,源源不断地发送 1 (灰色部分), Server 2 怎么检测结尾在哪里?

我们可以定义一些特殊的比特序列,用于定义开头结尾: 101010 表示开头, 010101 表示结尾。

pc28.am神测网 9

这时, Server 1 先发送 101010 (红色),告诉 Server 2 我要开始发数据了; 然后, Server 1 开始发送数据 1101011 (黑色部分); 最后, Server 1 发送 010101 (绿色),告诉 Server 2 数据发送完毕。 注意到,平时信道为 1 (灰色),也就是代表空闲状态。

原文地址: (coding-fan)

注:NTC为热敏电阻,输出为:单总线数字信号,单线双向串行通讯。

寻址

假设, antbee 发送(粗体)一个数据 11110000 。 由于导线是共享的,所有机器都可以检测到电平信号。 换句话讲, beecicada 都会收到这个数据 11110000 ,而 cicada 本不应该接收这个数据! 另一方面, bee 收到数据后,也不知道数据到底是谁发送给它的。

pc28.am神测网 10

因此,我们需要引入一些比特,用来标识数据的来源以及目的地。 我们的例子只有3台服务器,两个比特就足以唯一确定一台机器:

机器 比特
ant 00
bee 01
cicada 10

那么,发送数据时,额外加上两个比特用于表示来源机器,另外两个比特表示目标机器,问题不就解决了吗?

pc28.am神测网 11

bee 收到数据后,检查前两个比特(红色),值为 00 ,便知道是 ant 发出来的; 检查紧接着的两个比特(绿色),值为 01 ,与自己匹配上,便愉快地收下了。 相反, cicada 收到数据后,发现 01 和自己 10 匹配不上,便丢弃这个数据。

新引入比特所起的作用,在计算机网络中称为 寻址 。 这两个比特也就称为 地址 ,其中,红色为源地址,绿色为目的地址。 通过引入寻址,我们完美地解决了数据从哪来,到哪去的问题。

冲突仲裁

如果两台服务器同时往信道里发送数据,会发生什么事情呢?

pc28.am神测网 12

肯定冲突了嘛!一台发 0 ,一台发 1 ,那你说信道到底是 0 还是 1 ? 那么,冲突要怎么解决呢?

解决方式也简单,只需在硬件层面实现一种机制:在检测到两台服务器同时发送数据时,及时喊停,并协商到底由哪一方先发。

这时,你可能会想到,用一根电缆把两台服务器连接起来:

pc28.am神测网 13

复用/分用

信道只有一个,但是通讯需求是无穷无尽的——传输研究数值、文件打印、即时通讯,不一而足。 如何解决这个矛盾呢?套路还是一样的——引入新的比特。

假设,总的通讯需求就上面这3个,那么,2个额外的比特便解决了问题。

类型 比特
研究数据 00
文件打印 01
即时通讯 10

这时,假设 antbee 上报研究数据并打印一个文件:

pc28.am神测网 14

这样,通过新引入的紫色比特,我们实现了在同个信道上进行不同的通讯! bee 接收到数据后,根据紫色比特,决定数据如何处理。

接下来,从理论的视角来审视这个场景:

pc28.am神测网 15

信道只有一个,需要承载不同的通讯需求。 在发送端,通过加入紫色比特,将不同的数据通过一个共用信道发送出去,这个过程叫做 复用 ( Multiplexing ); 在接收端,从共用信道上接收数据,然后检查紫色比特决定数据如何处理,这个过程叫做 分用 ( Demultiplexing )。 在接下来的章节,我们将看到 复用 - 分用 这个概念贯彻计算机网络的始终。

pc28.am神测网 16

到目前为止,我们引入了 3 种不同的比特,分别是 源地址目的地址 以及 数据类型 。 对于这些比特的位数以及含义的约定,便成为 网络协议

总结

本节讨论了一个最简单的模型,解决两台服务器之间的通讯问题。 通过电缆,在两台机器间建立了一个理想的比特流传输信道。 这其实就是网络分层结构中最底层——物理层的作用:

  • 传输比特流
  • 依赖物理(电气)特性

这一层对开发人员来说,基本上是透明的,我们只需将其理解成一个比特流传输信道即可。 至于细节问题,高低电平啦,信号啦,各种物理特性啦,通通留给电子工程师去关心好啦!

pc28.am神测网 17通过电缆实现通讯

pc28.am神测网 18

总结

本节,我们解决了多台共用信道服务器间的通信问题,这相当于网络分层结构中的 数据链路层 。 数据链路层的主要作用包括:

  • 寻址
  • 复用/分用

进度

pc28.am神测网 19

物理课大家都学过,电线可以分为 低电平高电平 。 电平可以高低变化,这样不就可以传递信息了么: Server 1 控制电缆电平的高低, Server 2 检测电平的高低,这样就实现了 Server 1Server 2 发送数据啦!

pc28.am神测网 20

进度

pc28.am神测网 21

下一步

下一节,我们将通过 多服务器通讯问题 进入 数据链路层 的学习。

订阅更新,获取更多学习资料,请关注我们的 微信公众号 :

pc28.am神测网 22

pc28.am神测网 23

更进一步,可以将高低电平抽象成数学语言:我们用低电平表示 0 ,高电平表示 1 ,这样就得到一个理想化的信道:

注:上拉电阻情况下,配置为开漏输出,可以增加驱动能力,减小CPU功耗。

下一步

下一节,我们开始学习一个真实的数据链路层协议—— 以太网协议 。 届时,我们将看到 以太网协议 与本节虚构的协议别无二致。

订阅更新,获取更多学习资料,请关注我们的 微信公众号 :

pc28.am神测网 24

pc28.am神测网 25

pc28.am神测网 26理想化信道

pc28.am神测网 27

通过信道,双方可以传递一些 01 比特流。 例子中,我们传输的比特流是 1111010101... 。 比特流可以编码任意信息: 比如,我们用 1111 表示告诉对方本地开机了,用 0000 告诉对方本地准备关机了。

pc28.am神测网 28

到目前为止,我们是不是万事具备了呢? 一个比特流信道成为现实?——理论上是这样子的。 但是,现实世界往往要比理想化的模型复杂一些。

pc28.am神测网 29

pc28.am神测网 30信道无穷无尽

pc28.am神测网 31

首先,如上图,信道是无穷无尽的。 因为,信道状态要么为 0 ,要么为 1 ,没有一种表示空闲的特殊状态。

pc28.am神测网 32

pc28.am神测网 33结尾在哪?

pc28.am神测网 34pc28.am神测网 35

举个例子,如上图, Server 1Server 2 发送比特序列 101101001101 。 最后一个比特是 1 ,对应的电平是高电平。 发送完毕后,由于没有没有其他地方改变电缆的电平,所以还是维持高电平状态。 也就是说,信道看起来还是按照既定节拍,源源不断地发送 1Server 2 怎么检测结尾在哪里?

二.程序关键点:1)引脚输入与输出的准确切换,2)输出电平的准确延迟,3)输入电平的等待与延迟读取以及等待的时间限制。

我们可以定义一些特殊的比特序列,用于定义开头结尾: 101010 表示开头, 010101 表示结尾。

1.MCU如何设置开始信号?

pc28.am神测网 36.引入控制比特

/*
由MCU向DHT11发送一次开始信号,总线空闲状态为高电平,MCU把总线拉低至少18ms,
保证DHT11能检测到开始信号,主机发送开始信号后,可以切换到输入模式,或者切换到
高电平均可,切换到高电平时间通常为20~40us,然后开始读取响应信号.
*/
void DHT11_Rst(void)   
{                 
DHT11_IO_OUT();  //配置引脚为通用推挽输出模式
DAOBB = 0;  //拉低DQ
    SysTickDelay(20000);//至少18ms
DAOBB = 1; 
SysTickDelay(30);//主机拉高20~40us
}

这时, Server 1 先发送 101010 ,告诉 Server 2 我要开始发数据了; 然后, Server 1 开始发送数据 1101011 ; 最后, Server 1 发送 010101 ,告诉 Server 2 数据发送完毕。 注意到,平时信道为 1 ,也就是代表空闲状态。

2.MCU如何接受响应信号?

如果两台服务器同时往信道里发送数据,会发生什么事情呢?

/*
等待DHT11的回应
返回1:未检测到DHT11的存在
返回0:存在DHT11接受到主机的开始信号后,等待主机的开始信号结束,
然后发送80us的低电平响应信号,发送响应信号后,在把总线拉高80us,准备发送数据*/
u8 DHT11_Check(void)   
{   
u8 retry=0;
DHT11_IO_IN();//将A11口设为输入
  /*&&与<的优先级是<高于&&*/
    while (DHT11_DQ_IN&&retry<100)//DHT11会拉低40~80us
{
retry ;
SysTickDelay(1);//这里系统滴答函数要配置为1US的中断

if(retry>=100)return 1;
else retry=0;
    while (!DHT11_DQ_IN&&retry<100)//DHT11拉低后会再次拉高40~80us
{
retry ;
SysTickDelay(1);
}
if(retry>=100)return 1;   
return 0;
}

pc28.am神测网 37发送冲突:两台服务器同时发送数据

3.如何读取一个位的高低电平?前提是已经有响应信号,这样去读取数据才有意思。
一个位的高低电平是根据总线上的高电平的时间长度来判断的,说白了,就是低电平一旦结束,再过28us,总线上的电平为高,这个位的电平就是高电平,总线上的电平为低,这个位的电平就是低电平。所以我们只要等待总线上的低电平结束,过了28us以后再70us之前去读总线上的电平,就能知道具体的一位的电平是多少了。但我们不能无限制的等待低电平结束,假如器件故障或其他原因,总线上始终低电平,这样程序就会在等待中死去,所以我们必须加一个等待时间的限制,超过等待时间,我们就放弃这次等待。为了使读取后总线上的高低电平不影响下一次的读取数据,我们还加了一个高电平的限时等待。

肯定冲突了嘛!一台发 0 ,一台发 1 ,那你说信道到底是 0 还是 1 ? 那么,冲突要怎么解决呢?

/*从DHT11读取一个位,返回值:1/0。
每一bit数据都以50us的低电平时序开始,高电平的宽度决定了bit数据位的0或1,
高电平状态在26~28us时,表示数据位为0,高电平状态在70us时,表示数据位为1.
DHT11_DQ_IN是读取对应端口引脚的输入电平,在读之前,该引脚要配置为上拉下拉输入模式
*/
u8 DHT11_Read_Bit(void)  
{
  u8 retry=0;
while(DHT11_DQ_IN&&retry<100)//读取高电平中,等待变为低电平,/*&&与<的优先级是<高于&&*/
{
retry ;
SysTickDelay(1);
}
retry=0;
while(!DHT11_DQ_IN&&retry<100)//读取低电平中,等待变高电平
{
retry ;
SysTickDelay(1);
}
SysTickDelay(40);//等待40us
if(DHT11_DQ_IN)return 1;
else return 0;  
}

解决方式也简单,只需在硬件层面实现一种机制:在检测到两台服务器同时发送数据时,及时喊停,并协商到底由哪一方先发。

//从DHT11读取一个字节
//返回值:读到的数据
u8 DHT11_Read_Byte(void)    
{        
    u8 i,dat;
    dat=0;
for (i=0;i<8;i ) 
{
    dat<<=1; 
   dat|=DHT11_Read_Bit();
    }    
    return dat;
}

本节讨论了一个最简单的模型,解决两台服务器之间的通讯问题。 通过电缆,在两台机器间建立了一个理想的比特流传输信道。 这其实就是网络分层结构中最底层——物理层的作用:

//从DHT11读取一次数据
//temp:温度值(范围:0~50°)
//humi:湿度值(范围:20%~90%)
//返回值:0,正常;1,读取失败
u8 DHT11_Read_Data(u8 *temp,u8 *humi)    
{        
  u8 buf[5];
u8 i;
DHT11_Rst();
if(DHT11_Check()==0)
{
for(i=0;i<5;i )//读取40位数据
{
buf[i]=DHT11_Read_Byte();
}
if((buf[0] buf[1] buf[2] buf[3])==buf[4])
{
*humi=buf[0];
*temp=buf[2];
}
}else return 1;
return 0;     
}

  • 传输比特流
  • 依赖物理特性

这一层对开发人员来说,基本上是透明的,我们只需将其理解成一个比特流传输信道即可。 至于细节问题,高低电平啦,信号啦,各种物理特性啦,通通留给电子工程师去关心好啦!

pc28.am神测网 38新技能Get✔️

下一节,我们将通过 多服务器通讯问题 进入 数据链路层 的学习。

订阅更新,获取更多学习资料,请关注我们的 微信公众号 :

pc28.am神测网 39小菜学编程

本文由pc28.am发布于pc28.am神测网,转载请注明出处:pc28.am神测网:网络七层协商之数据链路层,互联

上一篇:windows下布置无需付费ssl证书 下一篇:没有了
猜你喜欢
热门排行
精彩图文