协议原理

设计思路

基本传输

本次实验我采用了程序模拟的方式实现。发送方和接收方都为一个数组,传输过程即为发送方数组向接收方数组传递数据,并使用随机数生成的方式模拟传输过程中可能出现的差错,并且传输时间也为一个在 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;
	}
}

运行效果