【编程之美】超时重传,滑动窗口,可靠性传输原理C语言实现
版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/lihuidashen/p/12800323.html
微信链接: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语言实现状态机(实用)
【超详细C语言】带你吃透贪吃蛇游戏之精髓
【编程之美】超时重传,滑动窗口,可靠性传输原理C语言实现的更多相关文章
- 【编程之美】常用于单片机的接口适配器模式C语言实现
版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://www.cnblogs.com/lihuidashen/p/128750 ...
- 7、滑动窗口套路算法框架——Go语言版
前情提示:Go语言学习者.本文参考https://labuladong.gitee.io/algo,代码自己参考抒写,若有不妥之处,感谢指正 关于golang算法文章,为了便于下载和整理,都已开源放在 ...
- TCP面试题之滑动窗口原理
TCP 滑动窗口 作用: 1. 提供TCP可靠性:对发送的数据进行确认 2. 流量控制:窗口大小随链路变化 一.TCP窗口机制 TCP中窗口大小是指tcp协议一次传输多少个数据.因为TCP是一个面向连 ...
- [TCP/IP] 滑动窗口
什么是滑动窗口? 滑动窗口机制是TCP协议的一种流量控制和防拥塞的机制. 滑动窗口的工作原理? 简单来讲,就是接收方和发送方分别保留一块缓冲区,作为接收和发送数据来使用,发送数据过程中,如果发送方发的 ...
- 彻底搞通TCP滑动窗口
在我们当初学习网络编程的时候,都接触过TCP,在TCP中,对于数据传输有各种策略,比如滑动窗口.拥塞窗口机制,又比如慢启动.快速恢复.拥塞避免等.通过本文,我们将了解滑动窗口在TCP中是如何使用的. ...
- storm 1.0版本滑动窗口的实现及原理
滑动窗口在监控和统计应用的场景比较广泛,比如每隔一段时间(10s)统计最近30s的请求量或者异常次数,根据请求或者异常次数采取相应措施.在storm1.0版本之前,没有提供关于滑动窗口的实现,需要开发 ...
- 源码分析 Alibaba sentinel 滑动窗口实现原理(文末附原理图)
要实现限流.熔断等功能,首先要解决的问题是如何实时采集服务(资源)调用信息.例如将某一个接口设置的限流阔值 1W/tps,那首先如何判断当前的 TPS 是多少?Alibaba Sentinel 采用滑 ...
- TCP超时重传、滑动窗口、拥塞控制、快重传和快恢复
TCP超时重传 原理是在发送某一个数据以后就开启一个计时器,在一定时间内如果没有得到发送的数据报的ACK报文,那么就重新发送数据,直到发送成功为止. 影响超时重传机制协议效率的一个关键参数是重传超时时 ...
- TCP协议可靠性是如何保证之滑动窗口,超时重发,序列号确认应答信号
原创文章首发于公众号:「码农富哥」,欢迎收藏和关注,如转载请注明出处! TCP 是一种提供可靠性交付的协议. 也就是说,通过 TCP 连接传输的数据,无差错.不丢失.不重复.并且按序到达. 但是在网络 ...
随机推荐
- Cygwin工具编译Ardupilot方法
注意:该编译方法生成的固件基于Chibios系统,如果想要Nuttx系统固件,需采用make编译,步骤见make编译说明部分. 软件安装准备 安装Cygwin 打开链接www.cygwin.com/i ...
- python文件封装成*.exe
python文件封装成*.exe文件(单文件和多文件) 环境:win10 64位 python3.7 原文: https://www.cnblogs.com/jackzz/p/9431923.html ...
- js数组的常用方法(10种)
数组的常用方法 数组在JavaScript中经常使用,如何对数组进行增删改非常重要,下面为数组的常用方法: 在数组末尾插入元素 arr.push(value),在数组的末尾添加一个或多个元素,并返回数 ...
- Spring装配Bean的三种方式+导入和混合配置
目录 Spring IoC与bean 基于XML的显式装配 xml配置的基本结构 bean实例的三种创建方式 依赖注入的两种方式 构造器注入方式 setter方法注入方式 利用命名空间简化xml 基于 ...
- python 报错:a bytes-like object is required, not 'str'
核心代码: def ipPools(numPage): headers = randomHeads() url = 'http://www.xicidaili.com/nn/' saveFsvFile ...
- Java 程序该怎么优化?(工具篇)
程序员:为什么程序总是那么慢?时间都花到哪里去了? 面试官:若你写的 Java 程序,出现了性能问题,该怎么去排查呢? 工欲善其事必先利其器,为你呈上一箩筐性能优化工具,必有一款满足你,废话不多说,直 ...
- 前端上传视频、图片、文件等大文件 组件Plupload使用指南
demo:https://blog.csdn.net/qq_30100043/article/details/78491993 Plupload上传插件中文帮助文档网址:http://www.phpi ...
- 【php】文件系统
一. 了解文件: a) 我们在Windows当中已知众多种文件类型:png.jpeg.jpg.gif.mp3.mp4.avi.rmvb.txt.doc.exl.ppt.php.exe b) 无论我们w ...
- Taro Next H5 跨框架组件库实践
作者:凹凸曼 - JJ Taro 是一款多端开发框架.开发者只需编写一份代码,即可生成各小程序端.H5 以及 React Native 的应用. Taro Next 近期已发布 beta 版本,全面完 ...
- .bundle文件如何安装
1. sudo chmod +x X.bundle 2. sudo X.bundle