停止等待协议的模拟实现

协议原理

请添加图片描述

设计思路

基本传输

本次实验我采用了程序模拟的方式实现。发送方和接收方都为一个数组,传输过程即为发送方数组向接收方数组传递数据,并使用随机数生成的方式模拟传输过程中可能出现的差错,并且传输时间也为一个在 50 - 150 ms 间的随机数,用一个迭代器来模拟此时发送方的数据位置。

传输过程为一个循环语句,终止条件为发送迭代器到达发送方数组的末尾位置。

选择重传

每次进行传输,传输时间就会累加,在一轮传输的最后判断累计时间是否超过了规定 tout,如果未超过,代表数据成功接收,发送迭代器自增 1。 否则,不进行操作,下一次循环将会再次尝试发送该数据。

舍弃重复帧

存在这么一种情况,接收方成功接收了发送方的数据,并返回了一个 ACK 帧,但是此 ACK 帧还未到达发送方就已被其判定为超时,那么发送方将会重新发送上一次的数据帧,若该数据帧成功到达接收方,那么接收方需要将该数据帧舍弃(因此上一次传输时接收方已成功接受了该数据帧)。实现方法是判断接受数组的最后一个元素(即上一次接收的元素)是否与此时接受的相同,若相同,则不接收,并重新发送 ACK 帧。

代码实现

#include<iostream>
#include<string>
#include<vector>
#include<Windows.h>
using namespace std;

struct myData
{
	int bin;
	string str;
	myData(int b, string s) : bin(b), str(s) {}
};

class ARQ {
public:
	void transmitData(vector<myData>& reciver, vector<myData>& sender) {
		srand((unsigned int)time(NULL));
		auto itSender = sender.cbegin();
		while (itSender != sender.cend()) {
			int sendBin = rand() % 2; // 传输过程数据可能出错
			double transTime = rand() % 101 + 50; // 随机传输时间为 50 - 150 ms
			myData sendData(sendBin, itSender->str); // 取数据帧
			cout << "sender: 正在发送第 " << itSender - sender.cbegin() << " 帧..." << endl;
			Sleep(transTime); // 数据传输过程
			bool isRight = sendData.bin; // 检错
			if (!reciver.empty() && reciver.back().str == sendData.str) { // 舍弃重复帧
				cout << "reciver: 丢弃重复帧,准备重新发送 ACK 帧。" << endl;
				isRight = true;
				transTime += rand() % 101 + 50;
				cout << "reciver: 正在发送 ACK 帧..." << endl;
				Sleep(transTime);
			}
			else if (isRight) { // 数据正确
				reciver.emplace_back(sendData); // 接收数据
				cout << "reciver: 数据成功接收,准备发送 ACK 帧。" << endl;
				transTime += rand() % 101 + 50;
				cout << "reciver: 正在发送 ACK 帧..." << endl;
				Sleep(transTime);
			}
			else { // 数据错误
				cout << "reciver: 数据错误,发送 NAK 帧。" << endl;
				transTime += rand() % 101 + 50;
				cout << "reciver: 正在发送 NAK 帧..." << endl;
				Sleep(transTime);
			}

			if (transTime < 250) { // 未超时
				if (isRight) {
					cout << "sender: 成功接收 ACK 帧,准备发送下一帧。" << endl << endl;
					++itSender;
				}
				else {
					cout << "sender: 成功接收 NAK 帧,准备重传。" << endl << endl;
				}
			}
			else { // 传输超时
				cout << "sender: 超时,准备重传。" << endl << endl;
			}
		}
	}
};

int main() {
	ARQ arq;
	vector<myData> reciver; // 初始时接收方为空
	vector<myData> sender = { myData(1, "Hello"),myData(1,"World"), myData(1, "!") }; // 初始化发送方
	arq.transmitData(reciver, sender);
	cout << "---------------------------------" << endl;
	cout << "数据传输结束,以下为接收者收到的数据:" << endl;
	for (const auto& s : sender) {
		cout << s.bin << " " << s.str << endl;
	}
}

运行效果

请添加图片描述

  • 2
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
StopWaitComm.vcproj 这是使用“应用程序向导”生成的 VC++ 项目的主项目文件。 它包含有关生成文件的 Visual C++ 版本的信息,以及 有关用“应用程序向导”所选择的平台、配置和 项目功能的信息。 StopWaitComm.h 这是应用程序的主头文件。 它包含其他 项目特定的头文件(包括 Resource.h),并声明 CStopWaitCommApp 应用程序类。 StopWaitComm.cpp 这是包含应用程序 类 CStopWaitCommApp 的主应用程序源文件。 StopWaitComm.rc 这是程序使用的所有 Microsoft Windows 资源 的列表。 它包含存储在 RES 子目录中 的图标、位图和光标。 可直接在 Microsoft Visual C++ 中编辑此文件。 项目资源包含在 2052 中。 res\StopWaitComm.ico 这是一个图标文件,用作应用程序的图标。 此 图标包含在主资源文件 StopWaitComm.rc 中。 res\StopWaitComm.rc2 此文件包含不由 Microsoft Visual C++ 编辑的资源。 应将所有不能由 资源编辑器编辑的资源放在此文件中。 ///////////////////////////////////////////////////////////////////////////// 应用程序向导将创建一个对话框类: StopWaitCommDlg.h、StopWaitCommDlg.cpp - 对话框 这些文件包含 CStopWaitCommDlg 类。 此类定义 应用程序主对话框的行为。 此对话框的模板包含在 StopWaitComm.rc 中,而此文件可以在 Microsoft Visual C++ 中进行编辑。 ///////////////////////////////////////////////////////////////////////////// 其他功能: ActiveX 控件 应用程序支持使用 ActiveX 控件。 ///////////////////////////////////////////////////////////////////////////// 其他标准文件: StdAfx.h、StdAfx.cpp 这些文件用于生成名为 StopWaitComm.pch 的预编译头文件 (PCH) 和名为 StdAfx.obj 的预编译类型文件。 Resource.h 这是标准头文件,它定义新资源 ID。 Microsoft Visual C++ 将读取并更新此文件。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值