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