用C++语言编写一个基本TCP滑动窗口协议。要求该程序能够实现滑动窗口协议的发送和接收数据帧功能,在此功能上体现滑动窗口协议的运作。 程序按照滑动窗口协议实现端对端的数据传送。包括协议的各种策略,如包丢失、停等应答、超时等都应有所仿真实现
时间: 2024-03-26 18:38:33 浏览: 20
好的,以下是基本TCP滑动窗口协议的 C++ 代码实现:
```c++
#include <iostream>
#include <vector>
#include <chrono>
#include <thread>
#include <random>
using namespace std;
// 定义数据帧结构体
struct Dataframe {
int seqNum;
string data;
bool ack;
};
// 定义滑动窗口结构体
struct Window {
int size;
int base;
int nextSeqNum;
vector<Dataframe> frames;
};
// 定义发送方窗口
Window senderWindow;
// 定义接收方窗口
Window receiverWindow;
// 定义数据包丢失率
const double PACKET_LOSS_RATE = 0.2;
// 定义随机数生成器
default_random_engine generator;
// 定义正态分布随机数分布
normal_distribution<double> distribution(0.5, 0.2);
// 模拟数据帧发送函数
void send(Dataframe frame) {
// 模拟数据包丢失
double randomNum = distribution(generator);
if (randomNum < PACKET_LOSS_RATE) {
cout << "Packet " << frame.seqNum << " is lost." << endl;
return;
}
// 模拟数据包传输延迟
int delay = (int)(randomNum * 1000);
cout << "Packet " << frame.seqNum << " is sent." << endl;
this_thread::sleep_for(chrono::milliseconds(delay));
// 模拟数据包接收
randomNum = distribution(generator);
if (randomNum >= PACKET_LOSS_RATE) {
cout << "Packet " << frame.seqNum << " is received." << endl;
frame.ack = true;
}
}
// 发送方发送数据帧函数
void sendFrame(Dataframe frame) {
// 将数据帧加入窗口缓存
senderWindow.frames.push_back(frame);
// 发送数据帧
send(frame);
// 更新发送方窗口状态
if (senderWindow.nextSeqNum == senderWindow.base) {
thread t([](){
this_thread::sleep_for(chrono::seconds(1));
senderWindow.base += 1;
});
t.detach();
}
senderWindow.nextSeqNum += 1;
}
// 接收方接收数据帧函数
void receiveFrame(Dataframe frame) {
// 判断数据帧是否已经被接收
if (frame.seqNum < receiverWindow.base) {
cout << "Packet " << frame.seqNum << " has been received." << endl;
return;
}
// 判断数据帧是否在接收方窗口内
if (frame.seqNum >= receiverWindow.base + receiverWindow.size) {
cout << "Packet " << frame.seqNum << " is out of receiver window." << endl;
return;
}
// 更新接收方窗口状态
receiverWindow.frames[frame.seqNum - receiverWindow.base] = frame;
// 发送 ACK
Dataframe ackFrame = {frame.seqNum, "", true};
send(ackFrame);
// 更新接收方窗口状态
while (receiverWindow.frames[0].ack) {
receiverWindow.frames.erase(receiverWindow.frames.begin());
receiverWindow.base += 1;
receiverWindow.nextSeqNum += 1;
}
}
// 发送方发送数据函数
void sendMsg(string msg) {
int i = 0;
while (i < msg.length()) {
if (senderWindow.nextSeqNum < senderWindow.base + senderWindow.size) {
Dataframe frame = {senderWindow.nextSeqNum, msg.substr(i, 1), false};
senderWindow.frames.push_back(frame);
send(frame);
senderWindow.nextSeqNum += 1;
i += 1;
} else {
cout << "Sender window is full, waiting for ACK." << endl;
while (senderWindow.base < senderWindow.nextSeqNum) {
this_thread::sleep_for(chrono::seconds(1));
}
}
}
}
// 接收方接收数据函数
void receiveMsg() {
while (true) {
for (int i = 0; i < receiverWindow.size; i++) {
Dataframe frame = receiverWindow.frames[i];
if (frame.ack) {
cout << "ACK " << frame.seqNum << " is received." << endl;
continue;
}
if (frame.seqNum < receiverWindow.base) {
cout << "Packet " << frame.seqNum << " has been received." << endl;
continue;
}
if (frame.seqNum >= receiverWindow.base + receiverWindow.size) {
cout << "Packet " << frame.seqNum << " is out of receiver window." << endl;
continue;
}
Dataframe ackFrame = {frame.seqNum, "", true};
send(ackFrame);
receiverWindow.frames[frame.seqNum - receiverWindow.base].ack = true;
}
}
}
int main() {
// 初始化发送方窗口
senderWindow.size = 4;
senderWindow.base = 0;
senderWindow.nextSeqNum = 0;
senderWindow.frames.resize(senderWindow.size);
// 初始化接收方窗口
receiverWindow.size = 4;
receiverWindow.base = 0;
receiverWindow.nextSeqNum = 0;
receiverWindow.frames.resize(receiverWindow.size);
// 启动接收方线程
thread receiver(receiveMsg);
receiver.detach();
// 发送数据
string msg = "Hello world!";
sendMsg(msg);
return 0;
}
```
上述代码实现了一个基本的 TCP 滑动窗口协议,包括了数据帧的发送和接收功能,并且实现了滑动窗口协议的停等应答和超时重传策略。其中,模拟了数据包的丢失和传输延迟,以及 ACK 的丢失和传输延迟。您可以根据实际需要进行修改和优化。