最小网元设计【阶段二】

阶段二:交互

2.1 本阶段预期

2.1 本阶段预期

在数据链路层实现帧定位、差错检测、差错控制以及流量控制功能。
在应用层实现字符编码方案以及图片编码方案。
帧结构图:
帧结构

2.2 帧定位

2.2.1 定义

帧定位技术是一种用来在一个比特流内分配或标记信道的技术。

2.2.2 方案

面向比特的首位字符界定法
笔者采用在帧头和帧尾各加 8 位标识的比特流 01111110。但是,仅仅如此的话会造成对帧头帧尾的误判,笔者考虑如果在数据中遇到连续的 6 个 1,那么将最后一个 1 替换为 0,但是仔细考虑,这样仍然 会造成误判,因此笔者采用:如果在发送端数据中遇到连续 5 个 1,那么在 最后一个 1 后面增添 1 个 0,例如:Data:11111100 -> 111110100。在接受端遇到 111110100 这种情况若判断出比特流为 9 位时,可去除连续 5 个 1 后 的 0,得到:11111100。

2.2.3 函数实现

发送机制:

char* get_frame(char* s);   //成帧函数 
bool define_fiveone(char* p, int index);//确定是否存在连续的 5个 1

接收机制:

char* locate_frame(char* s);//定位帧头帧尾,提取帧 
char* de_frame(char* s);//提取 8 位比特流

2.2.4 测试

发送机制:
帧定位测试(发方)
接收机制:
帧定位测试(收方)

2.3 差错检测

笔者采用循环冗余校验来检验误码。

2.3.1 定义

CRC 是一种根据网络数据包或计算机文件等数据产生简短固定位 数校验码的一种信道编码技术,主要用来检测或校验数据传输或者保存后可能出现的错误。它是利用除法及余数的原理来作错误侦测的。

2.3.2 方案

  • 编写函数计算 CRC 校验码,并添加至 8 位比特流后。 接收方通过重新计算 Q 来判断是否误码。 若出现误码, 则令
    ERROR_FLAG=true(ERROR_FLAG 是初始化为 false 的误帧标志) (需要注意的是,这里我们并不是用 FCS
    作为校验码,二而是 T/P 得 到的 Q 作为校验码,这样,接收方可以重新计算 Q 来进行比对,以发现是否出错。
  • 此外,笔者为每个帧加入序号,可以通过序号差来判断是否有帧丢失,重复帧的情况发生。

2.3.3 函数实现

发送机制:

char* get_crc(char* s);//计算 CRC 
char* add_crc(char* p, char* crc);将 CRC 插入 Data 后
int  de_serial_number(char* p);//将10进制帧序号转为2进制
char* add_serial_number(char* p, char* serial);//插入帧序号

接收机制:

char* get_crc(char* s);//计算 CRC 
char* add_crc(char* p, char* crc);将 CRC 插入 Data 后
int  de_serial_number(char* p);//将10进制帧序号转为2进制
char* add_serial_number(char* p, char* serial);//插入帧序号

2.3.4 测试

发送机制:
差错检测测试
接收机制:
差错检测
差错检测

2.4 差错控制

对于出现误码的帧,笔者采用停止等待协议进行差错的控制。

2.4.1 定义

停止等待协议用于通信系统中,两个相连的设备相互发送信息时使用,以确保信息不因丢包或包乱序而丢失,是最简单的自动重传请求方法。

2.4.2 方案

遵循以下原则:

  • 收方对收到的帧进行差错检测以及帧序号差(与本地)的判断
  • 收方只对成功接收的帧发送确认帧(ACK),其余一律丢弃
  • 发放每发一帧必须暂存此帧并停止等待确认帧,超时则重发
    关于确认帧:
    格式:将源、目的地址颠倒,ACK标识置为1,数据位为11111111
    在这里,考虑到反馈比特流可能 会出现误码,笔者规定,只要 8 位比特流内 1 的个数大于等于 4,则认为 不需要重传,8 位比特流内 1 的个数小于 4,则需要重传。这样就巧妙的解决了反馈信息误码造成的判断错误,毕竟误码率 p4 近似等于 0 了,几乎是不可能事件。
    停等协议示意图:
    停止等待协议

2.4.3 函数实现

发送机制:

char* add_dirty(char* p);//加入ACK标识位
bool if_ack(char* s);//判断是否为确认帧
bool get_dirty(char* p);//获得重传标志

接收机制:

char* get_retrans_frame(char* p);//获得确认帧

2.4.4 测试

发送机制:
差错控制测试
差错控制测试
差错控制测试
接收机制:
差错控制测试
差错控制测试

2.5 流量控制

起初并没有发现有什么地方需要进行流量控制的,但当发送多组数据时,接 收方并不能全部接收到,每隔一组数据都会漏接一个,这时候笔者意识到发送方向物理层灌输数据过快,一些数据被丢弃,于是笔者在网络层代码中,每次向物理层发送完数据后加 Sleep(10),实现了简单的流量控制。

2.6 函数封装

为了便于后续阶段的进行,笔者将交互阶段大部分功能封装在一个函数中,并且注释了不必要的打印信息。
发送机制:

char* encapsulate_frame(char* revData);//封装函数,获得最终向物理层发送的帧

接收机制:

char* decapsulate_frame(char* recbits);//解封函数,获得数据,并进行差错检测

测试:
函数封装测试
函数封装测试

2.7 字符编码

2.7.1 方案

采用ASCLL码进行对英文字母,标点,常用符号的编码及其解码。

2.7.2 函数实现

char* ascll_code(char ch);//将字符编码为8位比特流
char ascll_decode(char* p);//将8位比特流解码为字符
char* ten2two(int s);//ASCLL编码过程中用到的10进制转2进制函数
int two2ten(char* p);// ASCLL解码过程中用到的2进制转10进制函数

2.7.3 测试

发送机制:
字符编码测试
接收机制:
字符编码测试
(图中可能造成误解的地方:接收或发送仅显示了一帧,事实上有5帧,并不表明仅用一帧完成对“hello"的编码)

2.8 图片编码

2.8.1 方案

采用base64对图片进行编解码,发方先将图片编码为字符串,再将字符串编码为比特流,收方先将比特流译码为字符串,再用base64解码为图片并保存。
有关base64对图片编码的实现请参照基于base64的图片编解码方案—C语言实现

2.8.2 代码实现

const char* base64char = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";//base64编解码用到的字符
char* code_image(char* file_path);//图片编码
void decode_image(char* imageBase64, unsigned int imageSize);//图片解码
char* base64_encode(const unsigned char* bindata, char* base64, int binlength);//图片编码过程中使用的base64编码函数
int base64_decode(const char* base64, unsigned char* bindata) ;//图片解码过程中使用的base64解码函数
unsigned int get_imagesize(char* file_path);//获取图片大小(基于base64)

2.8.3 测试

发方检索用户输入的图片文件路径:”input.jpg”,进行编码发送
图片编码测试
图片编码测试
收方将收到的图片命名为”output.jpg”进行保存
图片编码测试*这种编码方式效率还是比较低的,本例中图片分辨率17×32,共发送27264帧,时长约270s.

2.9 心得体会

本阶段是整个项目的重中之重,务必要确保各种功能的稳健性,这样阶段三、四才能如鱼得水。
本文所提到的帧定位、差错检测以及差错控制是本项目的硬性要求,具体如何实现你可以参考现有的方案也可以自行设计,说到这,笔者当时凭空捏造停等协议,对于该协议的理解仅仅限于停止和等待两个关键词,最终花了一天半的时间才试错成功,却发现与现行的停等协议如出一辙,不过,不尝试犯错又怎知是错呢,虽然老师很建议参考现有的方案,但笔者认为经历过自己反复雕琢的东西才更有成就感不是吗。

发布了40 篇原创文章 · 获赞 12 · 访问量 5746

猜你喜欢

转载自blog.csdn.net/weixin_43488958/article/details/104055658
今日推荐