TCP 拥塞控制程序模拟
2020-06-06 本文已影响0人
AndyDennisRob
笔者花了一中午的时间,把早上学的TCP拥塞控制的情况进行模拟,写下这篇文章。
1.先来看看代码:
如果pip没配置镜像可以参考之前笔者写的另一篇博客,使用 pqi 来配置.那篇博客地址:
import time
import random
import matplotlib.pyplot as plt
"""
功能说明: 这是一个模拟使用快恢复和不适用快恢复的程序(TCP拥塞控制)
"""
def time_over(time_list: list, time_limit: int):
"""
:param time_list: 要判断的列表
:param time_limit: 限定的长度
:return: 是否传进来的序列到达一定长度
"""
if len(time_list) >= time_limit:
draw_picture(time_list)
return True
return False
def draw_picture(draw_list: list):
"""
:param draw_list: 要绘画的列表值
:return: None
"""
t = [i for i in range(1, len(draw_list) + 1)]
fig = plt.figure()
fig.suptitle('tcp congestion control simulation')
# 设置横轴标签
plt.xlabel("t")
# 设置纵轴标签
plt.ylabel("cwnd")
plt.plot(t, draw_list)
plt.show()
def congestion(start_cwnd: int, ssthresh: int, fast_recover: bool,
time_limit: int, each_sleep: float, con_range: tuple):
"""
:param start_cwnd: 开始时的报文数
:param ssthresh: 初始的ssthresh值
:param fast_recover:是否快恢复,即发送方是否收到三个重复确认
:param time_limit: 模拟的时间控制(建议不小于20)
:param each_sleep: 每个时间段模拟的时间.
:param con_range: 网络拥塞窗口的范围,左闭右闭
:return: cwnd_list,即拥塞窗口大小的列表
"""
# 网络可能的拥塞窗口最小值
con_min = con_range[0]
# 网络可能的拥塞窗口最大值
con_max = con_range[1]
# 发生拥塞时的窗口大小
congest_packet = random.randint(con_min, con_max)
# 调试时用到 congest_packet = 15
# 记录每一时刻的cwnd大小
cwnd_list = [start_cwnd]
cwnd = start_cwnd
# 判断时间是否结束
if time_over(cwnd_list, time_limit):
return cwnd_list
# 慢开始算法
while cwnd * 2 < ssthresh:
cwnd *= 2
cwnd_list.append(cwnd)
if time_over(cwnd_list, time_limit):
return cwnd_list
time.sleep(each_sleep)
cwnd = ssthresh
cwnd_list.append(cwnd)
if time_over(cwnd_list, time_limit):
return cwnd_list
# 拥塞控制算法
while cwnd < congest_packet:
cwnd += 1
cwnd_list.append(cwnd)
if time_over(cwnd_list, time_limit):
return cwnd_list
time.sleep(each_sleep)
# 此时网络拥塞了
# 判断是否进行快恢复
if fast_recover:
time.sleep(each_sleep)
# 以此类推
while True:
# 新的ssthresh值为发送窗口的一半
ssthresh = congest_packet // 2
cwnd = ssthresh
cwnd_list.append(cwnd)
if time_over(cwnd_list, time_limit):
return cwnd_list
# 新的发生拥塞时的窗口大小
congest_packet = random.randint(con_min, con_max)
# 调试时用到 congest_packet = 15
# 拥塞控制算法
while cwnd < congest_packet:
cwnd += 1
cwnd_list.append(cwnd)
if time_over(cwnd_list, time_limit):
return cwnd_list
time.sleep(each_sleep)
else:
time.sleep(each_sleep)
# 不进行快恢复
while True:
# 新的ssthresh值为发送窗口的一半
ssthresh = congest_packet // 2
cwnd = start_cwnd
cwnd_list.append(cwnd)
time.sleep(each_sleep)
# 慢开始算法
while cwnd * 2 < ssthresh:
cwnd *= 2
cwnd_list.append(cwnd)
if time_over(cwnd_list, time_limit):
return cwnd_list
time.sleep(each_sleep)
cwnd = ssthresh
cwnd_list.append(cwnd)
if time_over(cwnd_list, time_limit):
return cwnd_list
# 新的发生拥塞时的窗口大小
congest_packet = random.randint(con_min, con_max)
# 调试时用到 congest_packet = 15
# 拥塞控制算法
while cwnd < congest_packet:
cwnd += 1
cwnd_list.append(cwnd)
if time_over(cwnd_list, time_limit):
return cwnd_list
time.sleep(each_sleep)
if __name__ == '__main__':
la = congestion(2, 12, True, 300, 0, (20, 100))
lb = congestion(2, 12, False, 300, 0, (20, 100))
print("la:\n", la)
print("lb:\n", lb)
说明:由于网络情况是千变万化的,所以我这里用伪随机的方式生成拥塞时的窗口大小congest_packet.
然后这里模拟了300个单位时间内的情况.读者可以自行更改.
2.运行结果:
-
会画出两幅图(由于拥塞窗口大小每次都是随机产生,所以每次执行会不太一样)
这个是不采用快恢复的:
不使用快恢复
采用快恢复的:

-
控制台:这是cwnd窗口的变化序列
(其实右边还有,很长,这里截了一部分图)
cwnd窗口变化序列
3.感想: 通过自己编程序模拟, 使得自己对TCP拥塞控制的机制更加熟悉。由于时间仓促,代码就还没进行优化,感兴趣的读者可以去优化一下. 感谢观看.