计算机网络项目——最小网元设计(阶段二)

目录

  • 阶段目标
  • 设计描述
    • 1、帧结构
    • 2、帧定位
    • 3、差错检测
    • 4、差错控制
    • 5、流量控制
    • 6、长帧传输——分片
  • 测试情况
  • 其他想说的话

阶段目标

用链路层例程代码(LnkTester.sln)设计实现链路层上点到点之间的通信过程,具体包括:两点之间帧同步、、差错检测、差错控制、简单的流量控制。

设计描述

本阶段主要停留在链路层对等实体之间的通信,故我们设计时出于简便的测试的想法,先不考虑上下之间的数据传递带来的封装问题,将应用层融合为链路层。不过需要修改配置文件,将PHY和APP两层的配置文件改为PHY和LNK的两层文件,主要就是改一个APP层的名字,没有其他需求印象中是不太需要改其他参数的。

1、帧结构

不管是帧、数据包还是什么其他的数据形式也好,设计之初对于帧格式的设计一定是首尾的,这是一切的基础。在计算机网络的发展史中,协议的产生常常会伴随帧格式的改变。所以这是设计中的重头戏。

PS:设计采用面向位填充首尾定界法

01111110000000011001…011001111110
帧头定界符ACK标志位帧序号数据位CRC校验位帧尾定界符

2、帧定位

原理

帧定位采用面向位填充首尾定界法。帧头和帧尾标志固定为‘01111110’,在发送方封装成帧时通过get_frame()函数将帧内连续5个1后添加一个0,以便能够准确对帧进行定位。在接收方又通过读取bit流,读到首尾的“01111110”来进行定界,然后去除数据位中的连续5个1后的0.来还原真实数据位。(U8类型=char类型,此处这样定义,只是为了专门区别,用来表示单字节数据,这是指导书的说明,但我自己使用的时候则感觉多把他看成是1bit数据的形式。)

涉及函数

int get_frame(U8* s, int len);		//发送端成帧
int locate_frame(U8* s, int len,U8* bufSend);	//接收端提取帧

要点

  1. 需要对于连续8位数据的读取,判断首尾定界符,这是简单的for循环。
  2. 需要添加和提取5个1后面的0,这也是数据结构中基础的移位问题,要注意数据前移和后移时的到底是尾部先移动还是头部先移动。
  3. 除了简单的去除5个1后的0,可能要考虑因为去除CRC,ACK标志位和序列号时指针头的移动和len的变化问题,也可以简单在向上层转发函数中考虑。

3、差错检测

原理

差错检测采用CRC-4来产生校验码紧跟数据后面,其中CRC生成多项式采用固定G[5] = { 1,0,0,1,1 }利用crccode()函数来产生四位校验码,并在接收端用crcdecode()函数进行校验。校验错误则丢弃该帧,等待重传。(此处实际情况好像是多采用检错能力更强的CRC16,此处出于简便设计和运算速度,采用最短的CRC校验码)

涉及函数

int crccode(U8* s, int len);
//计算s的CRC校验位采用生成多项式G[5]={1,0,0,1,1}
bool crcdecode(U8* s, int len);		//接收方校验数据

要点

  1. 添加和删除校验码的移位问题,以及注意改变数据的长度len
  2. CRC的计算原理是采用模2除法,区别于二进制除法

4、差错控制

原理

对于数据在信道上进行传输的过程中可能产生的误码进行差错控制设计,我们采用停等协议进行差错控制(虽然后续阶段的设计发现,停等协议这种一发一收的方式还是不够高效,但设计是最简单的,其实可以尝试滑窗的GB_N和SR协议),增加1位ACK标识符和4位序列(由于是停等协议序号只有0000和1111),ACK标志位判断当前帧是数据帧(0)还是确认帧(1),并且判断收到的是否为正确序号的帧(相应确认帧序号总是为期待收到的下一帧的序列号)。确认帧的数据位采用八位全1(11111111)作为数据部分。为提高效率,收方收到ACK为1的帧数据位中判断收到数据位中有超过四个1即判断收到确认帧;同时序号中有三个及三个以上相同数字的即自动纠错判断帧序号。在发生差错和丢包时,利用Timeout()内部的重传函数将缓存下来的数据进行定时帧重传,直到接收到正确的确认帧,然后计时器开始变量isTimeStart停止。

涉及函数

int add_ack_seq(U8* s, int len);
//加入1位ACK标识位和4位序列号——————确认帧的ACK为1,并且ACK的数据bit流部分为11111111
bool isAck(U8* s);			//判断是否为确认帧
int get_ack_frame(U8* s, U8* ack_frame);	
//生成s对应的确认帧(帧序号为期待下一次接收到的帧序号)---------------------重要变量-----------------------------超时重传--
int TickTack = 0;//全局变量在Timeout()用来差错控制中的重传
bool isTimerStart = false;//全局计时器启动标志--缓存区--
U8* buffer = NULL;//全局的缓冲区,发送前用来装载可能重传的数据
int buflen = 0;//缓冲区储存的字符串长度--帧序号--
U8 SEQ[4] = { 0,0,0,0 };//四位序列号为全局变量,只有0000和1111,停等协议中异或交替出现

要点

  1. 在数据位头部,添加ACK标志位和帧序号涉及到的移位和len变化
  2. 帧序号由于是采用停等协议,故异或用1111和0000两个序号足矣,并且多位数据可以采用前向纠错(和数据位8位全1能够前向纠错同理),减少重传次数,提高传输效率;虽然停等协议效率本来就很低。
  3. 缓存区的全局变量在清空的时候建议采用提前分配一块较大的空间,然后不要采用free()释放的方式表示某次数据的缓存清空,而采用buflen=0长度清0来表示。因为在实测过程中因为前后次传输数据过程中,可能会由于超时时间的数值过小,导致出现连续多次释放同一块空间,导致以下报错。(而且反复申请和反复清空的操作本身就是一种很费资源的方式,参考数据栈清空时是因为真的不会再用那一块数据了,才清空的)。
    报错截图:(这个困扰了我很久,网上只知道是释放了空内存,后来花费很久才找到上面的解决办法)
    在这里插入图片描述

5、流量控制

在本例中,对于停等协议来说其实流量控制的意义不大,因为一发一收的机制本身就不会出现流量一股脑全怼进去的情况。但还是可以做流量控制,可以仿照重传,在Timeout()函数中设置一个阈值,和一个类似Ticktack的时钟变量,然后当达到阈值的时候,在sendtolower()前sleep一定的时间,达到流量控制的效果。(由于当时有点摸鱼,只随手写了个sleep,上面的说法才应该是正确的流控)

6、长帧传输——分片

这是当时自己没有做的一项拓展功能,但在后面传输图片或者文件的功能实现中,发现这是极其必要的。因为如果传输的数据过长,会导致数据产生错误而重传的概率提高,可能导致反复重传而传不过去。因此将数据进行分片多次传输,减小每次传输的帧长度,就有必要了。
虽然没有具体实现,但后续想了一下实现思路,还是比较简单:可以将数据按定长分段存入一个循环队列中,然后对每个小帧进行帧头和帧长的记录,然后依次封装发送。可以用一个标志变量记录当发送总数据量等于从上层接收到的帧长的时候,来表示一个完整的帧已经传输成功;或者可以用更多的帧序号加以区分。接收方则需要按帧序号重新组装数据放入一个新的内存即可。

测试情况

1、点到点数据传输情况

发送方:
在这里插入图片描述
接收方:
在这里插入图片描述

2、重传情况

发送方:
在这里插入图片描述

接收方:
在这里插入图片描述

其他想说的话

阶段二应该是后面两个阶段的基础,个人觉得阶段二主要是学会如何阅读源码,然后学会如何使用已有的一些例程函数,去方便我们的代码编写。(然后在调试过程中,最重要的就是学会看内存数据的变化,这是很重要的一点,能提高解决bug的效率)
不过好在这一阶段的代码,有老师的讲解视频可以参考,所以学着参考视频,放开手大胆去做,克服畏难情绪,好的结果才能回应这样一个好的开端!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/506939.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

key value vue 输出_Vue2.0 v-for 中 :key 到底有什么用?

v-for中不加:key貌似也能正常显示,那为什么要加:key呢?我们知道vue可以动态的改变页面的结构,比如在一个div里面插入一个span标签,看似简单的操作,底层还是很复杂的,它是如何实现的呢?因为页面的…

计算机网络项目——最小网元设计(阶段三)

目录阶段目标设计描述1、帧结构2、按目的转发3、反向地址学习4、未知广播测试情况其他想说的话阶段目标 本阶段主要完成链路层交换机的功能实现:单播目的地址判收、支持广播、有端口地址表、反向地址学习,并在含交换机的多网元情况下完成测试。 设计描…

token拦截器android_vue.js添加拦截器,实现token认证(使用axios)

什么是token?token是一个用户自定义的任意字符串,目前开发中,token都是在服务端生成并且token的值会保存到服务器后台。只有服务器和客户端知道这个字符串,于是,这个token就成了两者之间的秘钥,它可以让服务…

计算机网络项目——最小网元设计(阶段四)

目录阶段目标设计描述1、实体编址2、路由表设计3、路由配置4、路由器的存储转发5、端到端的图片传输测试情况其他想说的话阶段目标 本阶段需要对实体进行编址,实现NET层的IP地址到MAC层地址的映射,解决各层实体的标定区分和数据投递,同时网络…

扫一扫 移动端_移动端手机APP 身份证识别 手机扫一扫离线识别

证件识别是指能实现拍照自动输入身份信息,让用户完全告别手动输入身份证、驾驶证、行驶证等证件信息。它支持Android、 iOS 、Java、Linux等多终端形式接入,电 一山一,领九九,六八九八菱还能通过多样化的结果输出,满足…

电脑解锁后黑屏有鼠标_电脑开机黑屏只有鼠标

电脑开机黑屏只有鼠标经常使用电脑的朋友都会遇到电脑的各种故障,例如电脑开机黑屏只有鼠标,那么该怎么办呢?下面一起来看看电脑开机黑屏只有鼠标的解决办法。方法一、如果自己对电脑不懂的话,最简单的方法就是强制关机,这个关机…

figma应用——面向用户的咖啡点单APP的设计过程记录

目录概述设计阶段1、Brainstorm2、用户分析(1)用户画像(2)竞品分析(3)用户旅程地图(4)用户需求分析3、点单APP的demo设计(1)整体布局逻辑概览(2&a…

java右移位_java 、移位操作方法

<java" id"highlighter_505373">以上是正整数&#xff0c;运算结果如下。接下来看看将负数进行左移2位操作是什么情况&#xff0c;运算结果如下。为什么会-10的二进制会出现这么多的1呢&#xff1f;仔细数一下刚好有32位。首先需要了解的是java负数存储是…

打docker镜像_使用docker构建自己的镜像

在docker中&#xff0c;我们使用docker build构建一个新的镜像&#xff0c;构建镜像之前需要去编写Dockerfile这个文件才能否建一个新的镜像。官方文档&#xff1a;https://docs.docker.com/engine/reference/builder/#fromFROM&#xff1a;用于指定基础镜像RUN&#xff1a;构建…

3d打印主要的切片参数类型_3D打印混凝土工艺参数对成型精度的影响

3D打印混凝土技术作为新兴技术&#xff0c;由于其不需要模板&#xff0c;节省大量劳动力和可打印复杂造型的特点&#xff0c;得到了大家的关注。但是&#xff0c;利用3D打印技术建造想要的结构&#xff0c;成型精度是必须考虑的一个问题。成型精度受材料性能、打印设备及打印工…

web中hasmoreelements_Web开发模式【Mode I 和Mode II的介绍、应用案例】

开发模式的介绍在Web开发模式中&#xff0c;有两个主要的开发结构&#xff0c;称为模式一(Mode I)和模式二(Mode II).首先我们来理清一些概念吧&#xff1a;DAO(Data Access Object)&#xff1a;主要对数据的操作&#xff0c;增加、修改、删除等原子性操作。Web层&#xff1a;界…

网络传输大端序_大端、小端与网络字节序

大端(Big-Endian)&#xff0c;小端(Little-Endian)以及网络字节序的概念在编程中经常会遇到&#xff0c;网络字节序(Network Byte Order)一般是指大端(Big-Endian&#xff0c;对大部分网络传输协议而言)传输&#xff0c;大端小端的概念是面向多字节数据类型的存储方式定义的&am…

poi的sax模式读取xls_POI SAX 如何修改大excel 文件内容-问答-阿里云开发者社区-阿里云...

I think POI is using too much memory! What can I do?This one comes up quite a lot, but often the reason isnt what you might initially think. So, the first thing to check is - whats the source of the problem? Your file? Your code? Your environment? Or …

cupload怎么保存图片_原生js的图片上传插件cupload

插件描述&#xff1a;支持图片预览、像素限制、大小限制、多图上传、更新模式下页面初始化加载图片更新时间&#xff1a;2020-09-25 00:23:49更新说明&#xff1a;添加 删除时&#xff0c;同时删除服务器图片的功能&#xff0c;文档提供php实例。添加参数Url参数更新 {ele: &q…

mysql 半同步_mysql 主从同步 与 半同步

mysql主从同步复制定义主从同步使得数据可以从一个数据库服务器复制到其他服务器上&#xff0c;在复制数据时&#xff0c;一个服务器充当主服务器(master)&#xff0c;其余的服务器充当从服务器(slave)。通过配置文件&#xff0c;可以指定复制所有的数据库&#xff0c;某个数据…

mysql内存数据库性能_Mysql内存表配置及性能测试

centos7 mysql数据库安装和配可以参考一下文章&#xff0c;基本照做就可以了(我选的方法二)&#xff1a;http://www.cnblogs.com/starof/p/4680083.html说到内存表&#xff0c;首先有两个概念简单区分下&#xff1a;1.临时表&#xff1b;2.内存表&#xff1b;临时表与内存表的区…

mysql字符集排序规则_MySQL原理 - 字符集与排序规则

任何计算机存储数据&#xff0c;都需要字符集&#xff0c;因为计算机存储的数据其实都是二进制编码&#xff0c;将一个个字符&#xff0c;映射到对应的二进制编码的这个映射就是字符编码(字符集)。这些字符如何排序呢&#xff1f;决定字符排序的规则就是排序规则。查看内置字符…

mysql服务器默认操作字符集,如何在mysql中找到默认服务器字符集?

Using MySQL on FreeBSD 8.2. How do I find out the default server character set? Is there some command I can run or file I can check?UPDATEActually I want to know how to find both the default server character set and the current server character set.解决方…

mysql异常修复_MySQL错误修复:Table xx is marked as crashed and last (automatic?) repair failed...

问题一 Table xx is marked as crashed and last (automatic?) repair failed有开发找到我&#xff0c;说数据库坏了&#xff0c;连不上数据库&#xff0c;看了下 MySQL 的错误日志&#xff0c;报错如下&#xff1a;Error: Table ./db_name/table_name is marked as crashed a…

mysql 改变表的类型吗_mysql中修改表类型所带来的问题探讨

对于MySQL数据库&#xff0c;如果你要使用事务以及行级锁就必须使用INNODB引擎。如果你要使用全文索引&#xff0c;那必须使用myisam,那如何修改修改MySQL的引擎为INNODB呢&#xff0c;下面介绍一个修改方法。对于MySQL数据库&#xff0c;如果你要使用事务以及行级锁就必须使用…