利用c语言实现编程实现四种拥塞控制方法。要求: ① 程序具备必要的输入提示、输出提示。 ② 程序输入:初始门限值、传输轮次。 ③ 根据用户输入的“发生超时”或“收到三次重复确认”时的传输轮次实施拥塞控制。 ④ 程序输出:各传输轮次的拥塞窗口值。 ⑤ 可查询单个传输轮次的拥塞窗口值。 ⑥ 考虑到实际的TCP拥塞窗口以字节为单位。
时间: 2024-03-20 15:43:40 浏览: 67
好的,这是一个比较复杂的问题,需要一些时间来回答。首先,四种拥塞控制方法分别是:慢启动、拥塞避免、快重传和快恢复。
在c语言中,我们可以使用一个结构体来记录每个传输轮次的数据,包括拥塞窗口值、发送和接收的字节数等等。我们可以定义以下结构体:
```
struct TransmissionRound {
int congestion_window; // 拥塞窗口值
int bytes_sent; // 发送的字节数
int bytes_received; // 接收的字节数
int timeout_occurred; // 是否发生超时
int triple_ack_received; // 是否收到三次重复确认
};
```
然后,我们可以提示用户输入初始门限值和传输轮次:
```
printf("请输入初始门限值:");
scanf("%d", &initial_threshold);
printf("请输入传输轮次数:");
scanf("%d", &num_transmission_rounds);
```
接下来,我们可以使用一个循环来模拟每个传输轮次。在每个传输轮次中,我们需要记录拥塞窗口值、发送和接收的字节数等等。然后,我们需要根据用户输入的“发生超时”或“收到三次重复确认”时的传输轮次实施拥塞控制。最后,我们需要输出每个传输轮次的拥塞窗口值。
以下是一个示例代码,其中包含了慢启动、拥塞避免、快重传和快恢复四种拥塞控制方法的实现:
```
#include <stdio.h>
#define MSS 1460 // 最大报文段长度
#define ALPHA 0.125 // 拥塞避免算法中的参数
#define BETA 0.25 // 拥塞避免算法中的参数
struct TransmissionRound {
int congestion_window;
int bytes_sent;
int bytes_received;
int timeout_occurred;
int triple_ack_received;
};
int main() {
int initial_threshold;
int num_transmission_rounds;
printf("请输入初始门限值:");
scanf("%d", &initial_threshold);
printf("请输入传输轮次数:");
scanf("%d", &num_transmission_rounds);
struct TransmissionRound transmission_rounds[num_transmission_rounds];
// 慢启动阶段
int current_congestion_window = MSS;
int current_bytes_sent = 0;
int current_bytes_received = 0;
int current_timeout_occurred = 0;
int current_triple_ack_received = 0;
for (int i = 0; i < num_transmission_rounds; i++) {
transmission_rounds[i].congestion_window = current_congestion_window;
transmission_rounds[i].bytes_sent = current_bytes_sent;
transmission_rounds[i].bytes_received = current_bytes_received;
transmission_rounds[i].timeout_occurred = current_timeout_occurred;
transmission_rounds[i].triple_ack_received = current_triple_ack_received;
printf("传输轮次 %d:拥塞窗口值为 %d\n", i + 1, current_congestion_window);
if (current_timeout_occurred || current_triple_ack_received) {
// 发生超时或收到三次重复确认
current_congestion_window = initial_threshold;
current_timeout_occurred = 0;
current_triple_ack_received = 0;
} else {
// 未发生超时或未收到三次重复确认
current_bytes_sent += current_congestion_window;
current_congestion_window *= 2;
if (current_bytes_sent - current_bytes_received >= current_congestion_window * MSS) {
// 拥塞窗口达到门限值
current_congestion_window = initial_threshold;
}
}
}
// 拥塞避免阶段
current_congestion_window = initial_threshold;
for (int i = 0; i < num_transmission_rounds; i++) {
transmission_rounds[i].congestion_window = current_congestion_window;
transmission_rounds[i].bytes_sent = current_bytes_sent;
transmission_rounds[i].bytes_received = current_bytes_received;
transmission_rounds[i].timeout_occurred = current_timeout_occurred;
transmission_rounds[i].triple_ack_received = current_triple_ack_received;
printf("传输轮次 %d:拥塞窗口值为 %d\n", i + 1, current_congestion_window);
if (current_timeout_occurred || current_triple_ack_received) {
// 发生超时或收到三次重复确认
current_congestion_window = initial_threshold;
current_timeout_occurred = 0;
current_triple_ack_received = 0;
} else {
// 未发生超时或未收到三次重复确认
current_bytes_sent += current_congestion_window;
if (current_bytes_sent - current_bytes_received >= current_congestion_window * MSS) {
// 拥塞窗口达到门限值
current_congestion_window = current_congestion_window / 2;
}
current_congestion_window += MSS * ALPHA / current_congestion_window;
}
}
// 快重传和快恢复阶段
current_congestion_window = initial_threshold;
int current_duplicate_ack_count = 0;
int current_ssthresh = initial_threshold;
for (int i = 0; i < num_transmission_rounds; i++) {
transmission_rounds[i].congestion_window = current_congestion_window;
transmission_rounds[i].bytes_sent = current_bytes_sent;
transmission_rounds[i].bytes_received = current_bytes_received;
transmission_rounds[i].timeout_occurred = current_timeout_occurred;
transmission_rounds[i].triple_ack_received = current_triple_ack_received;
printf("传输轮次 %d:拥塞窗口值为 %d\n", i + 1, current_congestion_window);
if (current_timeout_occurred) {
// 发生超时
current_congestion_window = MSS;
current_ssthresh = current_congestion_window / 2;
current_timeout_occurred = 0;
current_duplicate_ack_count = 0;
} else if (current_triple_ack_received) {
// 收到三次重复确认
current_ssthresh = current_congestion_window / 2;
current_congestion_window = current_ssthresh + 3 * MSS;
current_triple_ack_received = 0;
current_duplicate_ack_count = 0;
} else {
// 未发生超时或未收到三次重复确认
current_bytes_sent += current_congestion_window;
if (current_bytes_sent - current_bytes_received >= current_congestion_window * MSS) {
// 拥塞窗口达到门限值
current_congestion_window = current_ssthresh;
current_duplicate_ack_count = 0;
} else {
// 拥塞窗口未达到门限值
current_duplicate_ack_count++;
if (current_duplicate_ack_count == 3) {
// 收到三个重复确认
current_ssthresh = current_congestion_window / 2;
current_congestion_window = current_ssthresh + 3 * MSS;
current_duplicate_ack_count = 0;
} else {
// 拥塞避免算法
current_congestion_window += MSS * BETA / current_congestion_window;
}
}
}
}
return 0;
}
```
在程序运行时,用户可以查询单个传输轮次的拥塞窗口值。例如,用户输入“3”时,程序会输出第三个传输轮次的拥塞窗口值:
```
int transmission_round_number;
printf("请输入传输轮次号:");
scanf("%d", &transmission_round_number);
printf("传输轮次 %d 的拥塞窗口值为:%d\n", transmission_round_number, transmission_rounds[transmission_round_number - 1].congestion_window);
```
阅读全文