开发者社区> 技术让梦想更伟大-李肖遥> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

【编程之美】超时重传,滑动窗口,可靠性传输原理C语言实现

简介: 最近在做无线传输的通信协议实现,这里涉及到超时重传,窗口移动,可靠性传输的问题,有些一些心得,也有很多的调试历程,与大家分享,当然源码不会开源,但是思想会毫无保留.
+关注继续查看

微信链接:https://mp.weixin.qq.com/s/LMBklt3xyZR2mu076lguCg

最近在做无线传输的通信协议实现,这里涉及到超时重传,窗口移动,可靠性传输的问题,有些一些心得,也有很多的调试历程,与大家分享,当然源码不会开源,但是思想会毫无保留.
    

首先我们看重传原理ARQ

ARQ(AutomaticRepeat reQuest,自动重传请求)是在数据链路层(MAC)实现的一种可靠性传输机制。其重传原理是发送端先将数据链路层的数据SDU按照固定的ARQ块大小来进行分片,最后剩下的数据不管多小都分为一个分片,接着为每个分片进行编号BSN(Block Sequence Number),如下图所示:

ARQ机制中SDU分片和BSN示意图

随后确定发送端的ARQ滑窗,即:将第一个发送PDU块作为ARQ发送窗口的起始PDU块ARQ_TX_WINDOW_START,接下来发送的下一个PDU块作为ARQ发送下一个PDU块ARQ_TX_NEXT_BSN。当发送的1个或N个PDU块被接收端确认接收成功后,其滑窗的起始PDU块ARQ_TX_WINDOW_START会加1或N,即:往后面滑1或N格,而下一个PDU块始终指到未发送PDU块的第1个。

同时,接收端也会根据接收情况来确定接收ARQ滑窗,即:通过ARQ接收起始PDU块ARQ_RX_WINDOW_START和接收ARQ滑窗大小ARQ_RX_WINDOW_SIZE两个参数来确定该滑窗大小。当在滑窗内的PDU块全部接收到后,会确认这次接收PDU的结果,如果有个别PDU块接收失败,则在后续的反馈IE中指出来,让发送端进行重传,重传最大次数来控制重传次数,否则就直接将接收ARQ滑窗往后滑,ARQ接收起始PDU块ARQ_RX_WINDOW_START会滑到还未接收PDU块的第1个,整个滑窗整体往后滑动。
以上的传输过程请参考下图:

ARQ传输机制原理图

那么怎么实现呢?

对于单个数据包来说,是很简单的,其ARQ状态机如下

对于需要窗口传输的重传机制来说,如图所示,

发送窗口只有收到对端对于本段发送窗口内字节的ACK确认,才会移动发送窗口的左边界。
接收端可以根据自己的状况通告窗口大小,从而控制发送端的接收,进行流量控制。

我们来定义数据结构
//数据索引

typedef struct {
  int status;
  int dataID;
  u16* Recvbuffer;
  int len;
}CommDataIndex;

//包的状态

typedef struct{
  int id;
  int crc;
}PacketStatus;

//发送状态

typedef struct{
  int dataID;
  int iRetries;
  int iResendTimerID;//重传定时器
  int iCycleTimerID; //生命周期定时器

}SendStatus;

//窗口信息

typedef struct {
  int winSize;
  SendStatus status[wSize];
  int minID;
  int maxID;

}WINMSG;

//数据类型

enum
{
  RTS=0,
  CTS,

  ACKNAK,
  payload,

}DATATYPE;

数据结构定义如下图,当有数据需要发送时,先申请动态内存缓存数据,最多缓存20包数据,数据的具体内容如CommDataIndex中所示,包含数据ID序号、数据buffer、数据长度;窗口的内容(包含窗口大小,窗口中每包数据发送状态,窗口中最小最大的数据ID序号) 如winMsg所示;数据包发送状态(包含数据ID,重发次数,重发定时器,生命周期定时器)如下Status所示。

发送端具体流程:
有数据发送时,先判断CommDataIndex数组中是否有空的位置,如果为空则将数据放入,最多缓存20包数据;

判断窗口是否满状态,当窗口不是满状态时,则可以发送数据,更新窗口信息(窗口中的最小最大ID,发送状态),启动发送状态中的定时器、更新重传次数;

当返回ack,则表示发送成功,判断是哪一包发送成功,找到这一包在commDataIndex的位置,并且清空,释放内存,找到这一包在窗口中的位置,清除这个位置窗口的发送状态信息(重传次数,数据ID),关闭这个窗口位置的定时器;如果这一包是窗口中最小的ID值,则可以移动窗口,进行下一包的传输,更新窗口中最小最大ID值

当返回nak,则表示发送失败,判断是哪一包发送失败,找到这一包在winMsg的位置,关闭窗口中对应的定时器,此时进行重发,更新发送状态status,更新重传次数,并且开启窗口中对应的定时器;当重传次数超过4次时,关闭对应的定时器,清空窗口发送状态的信息,重传次数,数据ID,找到这一包在commDataIndex的位置,并且清空,释放内存。

当没有响应消息时,表示发送超时,窗口对应的定时器ID构造事件传递给通信任务的定时器事件接收ID中,在发送端事件ID中处理,首先关闭定时器,找到定时器对应的窗口的位置,更新对应窗口发送状态信息,更新重传次数,当重传次数超过4次时,关闭对应的定时器,清空窗口发送状态的信息,重传次数,数据ID。进行重传操作,并且启动定时器。

当数据发送时长到达重传生命周期定时器限值时,表示整包数据没有在规定的时间里发送成功,此时关闭对应窗口的定时器,清空对应的窗口信息以及这一包数据的缓存信息,如果此时发现缓存数据中有数据需要发送,则进行发送,更新对应的窗口信息。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
《C语言编程初学者指南》一1.10 编程挑战
本节书摘来自华章出版社《C语言编程初学者指南》一书中的第1章,第1.10节,作者【美】Keith Davenport(达文波特) , M1ichael Vine(维恩),更多章节内容可以访问云栖社区“异步社区”公众号查看 1.10 编程挑战 1.学习附录B中的Vim快速指南。
1345 0
《C语言编程初学者指南》一2.12 编程挑战
本节书摘来自华章出版社《C语言编程初学者指南》一书中的第2章,第2.12节,作者【美】Keith Davenport(达文波特) , M1ichael Vine(维恩),更多章节内容可以访问云栖社区“异步社区”公众号查看 2.12 编程挑战 1.假设a=5、b=1、x=10且y=5,编写一个程序,使用一个单个的printf()函数输出表达式f = (a – b)(x – y)的结果。
1490 0
第八章 数组《C语言程序设计现代方法(第2版)》读书笔记
我们所见的变量都只是 标量(scalar ):标量具有保存单一数据项的能力。C语言也支持 聚合 (aggregate )变量,这类变量可以存储一组一组的数值。在 C 语言中一共有两种聚合类型: 数组 (array)和结构(structure )。
53 0
《C语言程序设计进阶教程》一1.1 编译
本文讲的是C语言程序设计进阶教程一1.1 编译,本节书摘来华章计算机《C语言程序设计进阶教程》一书中的第1章,第1.1节, Intermediate C Programming[美] 陆永祥(Yung-Hsiang Lu) 著 徐东 译 译更多章节内容可以访问云栖社区“华章计算机”公众号查看。
2265 0
《C语言程序设计进阶教程》一3.1.3 编程后
本文讲的是C语言程序设计进阶教程一3.1.3 编程后,本节书摘来华章计算机《C语言程序设计进阶教程》一书中的第3章,第3.1.3节, Intermediate C Programming[美] 陆永祥(Yung-Hsiang Lu) 著 徐东 译 译更多章节内容可以访问云栖社区“华章计算机”公众号查看。
1420 0
《C语言程序设计进阶教程》一3.1.2 编程中
本文讲的是C语言程序设计进阶教程一3.1.2 编程中,本节书摘来华章计算机《C语言程序设计进阶教程》一书中的第3章,第3.1.2节, Intermediate C Programming[美] 陆永祥(Yung-Hsiang Lu) 著 徐东 译 译更多章节内容可以访问云栖社区“华章计算机”公众号查看。
866 0
《C语言程序设计进阶教程》一3.1.1 编程前
本文讲的是C语言程序设计进阶教程一3.1.1 编程前,本节书摘来华章计算机《C语言程序设计进阶教程》一书中的第3章,第3.1.1节, Intermediate C Programming[美] 陆永祥(Yung-Hsiang Lu) 著 徐东 译 译更多章节内容可以访问云栖社区“华章计算机”公众号查看。
1038 0
《C语言程序设计进阶教程》一第3章 预防、检测及消除bug
本文讲的是C语言程序设计进阶教程一第3章 预防、检测及消除bug,本节书摘来华章计算机《C语言程序设计进阶教程》一书中的第2章,第2.6.2节, Intermediate C Programming[美] 陆永祥(Yung-Hsiang Lu) 著 徐东 译 译更多章节内容可以访问云栖社区“华章计算机”公众号查看。
889 0
《C语言及程序设计》实践参考——完数
返回:贺老师课程教学链接  项目要求 【项目1-完数】一个数如果恰好等于它的因子之和,这个数就称为“完数”。例如6=1+2+3,再如8的因子和是7(即1+2+4),8不是完数。(1)输入一个数n,判断n是否是完数[参考解答] 解1: #include <stdio.h> int main( ) { int n,s,m; printf("输入n:"); s
824 0
C语言及程序设计初步例程-14 指针及其运算
贺老师教学链接  C语言及程序设计初步 本课讲解 例 通过指针变量访问整型变量 #include <stdio.h> int main( ) { int a,b; int *p1,*p2; a=100; b=10; p1=&a; p2=&b; printf("%d %d\n", a, b); print
981 0
文章排行榜
最热
最新
相关课程
更多
相关电子书
更多
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载
冬季实战营第三期:MySQL数据库进阶实战
立即下载