一、实验要求
1. 掌握TCP进行拥塞控制的四种算法:慢开始、拥塞避免、快重传、快恢复的工作原理;
2. 编程实现拥塞控制算法。
二、实验环境
操作系统为Windows的计算机,安装有C、C++、Java、Python等编程工具。
三、实验要求
(1) 阅读互联网标准RFC5681文档。
(2) 掌握RFC5681的四种拥塞控制方法工作原理。
(3) 编程实现四种拥塞控制方法。要求:
① 程序具备必要的输入提示、输出提示。
② 程序输入:初始门限值、传输轮次。
③ 根据用户输入的“发生超时”或“收到三次重复确认”时的传输轮次实施拥塞控制。
④ 程序输出:各传输轮次的拥塞窗口值。
⑤ 可查询单个传输轮次的拥塞窗口值。
⑥ 考虑到实际的TCP拥塞窗口以字节为单位。
(4) 画图描述出拥塞窗口的变化曲线,可参考下图。(选做内容)
PS!本代码参考文章:http://t.csdnimg.cn/Dexca,是在其基础上稍作改进,基本实现了该作者提出的不足之处。
四、代码实现
import numpy as np
from matplotlib import pyplot as plt
import matplotlib.font_manager as fm
# 设置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei'] # 设置默认字体为黑体
plt.rcParams['axes.unicode_minus'] = False # 解决负号显示问题
def input_int(prompt):
while True:
try:
return int(input(prompt))
except ValueError:
print("输入无效,请输入一个整数。")
# 程序输入
cwin = input_int('请输入初始拥塞窗口大小(单位:字节):') # 拥塞窗口
ssthresh = input_int('请输入初始阈值大小(单位:字节):') # 初始阈值
# 输入超时发生的传输轮次
timeout_rounds = input("请输入超时发生时的传输轮次(多个轮次用逗号分隔,没有则输入-1):")
ifTimeoutRoundIndex = list(map(int, timeout_rounds.split(','))) if timeout_rounds else []
# 输入重传发生的传输轮次
retransmission_rounds = input("请输入重传发生时的传输轮次(多个轮次用逗号分隔,没有则输入-1):")
ifReTransmissionRoundIndex = list(map(int, retransmission_rounds.split(','))) if retransmission_rounds else []
roundCount = input_int("请输入传输轮次:") # 传输轮次
# 算法
listXResult = [] # 后期绘图用的x坐标集
listYResult = [] # 后期绘图用的y坐标集
for roundIndex in range(roundCount):
print(f"第 {roundIndex} 轮:拥塞窗口大小:{cwin} 字节")
# 图:收集x, y坐标
listXResult.append(roundIndex)
listYResult.append(cwin)
# 先判断,是否超时或重传
if roundIndex in ifTimeoutRoundIndex:
ssthresh = cwin // 2
cwin = 1
continue
if roundIndex in ifReTransmissionRoundIndex:
ssthresh = cwin // 2
cwin = ssthresh
# 慢启动
if cwin < ssthresh:
cwin *= 2
if cwin > ssthresh:
cwin = ssthresh
# 拥塞避免
elif cwin >= ssthresh:
cwin += 1
# 查询单个传输轮次的拥塞窗口值
while True:
query_round = input("请输入要查询的传输轮次(输入-1退出查询):")
if query_round == '-1':
break
try:
query_round = int(query_round)
if 0 <= query_round < roundCount:
print(f"第 {query_round} 轮:拥塞窗口大小:{listYResult[query_round]} 字节")
else:
print("输入的传输轮次超出范围,请重新输入。")
except ValueError:
print("输入无效,请输入一个整数。")
# 绘制拥塞窗口变化曲线
plt.xlabel("传输次数 roundIndex")
plt.ylabel("拥塞窗口 cwin(单位:字节)")
plt.plot(listXResult, listYResult, 'r')
plt.grid() # 添加网格
plt.title('拥塞窗口变化曲线')
plt.show()
另外,还有可以改进的部分,添加输入格式检查,增强代码健壮性。
代码仅供参考。