TCP 拥塞控制程序模拟

2020-06-06  本文已影响0人  AndyDennisRob

笔者花了一中午的时间,把早上学的TCP拥塞控制的情况进行模拟,写下这篇文章。

1.先来看看代码:

如果pip没配置镜像可以参考之前笔者写的另一篇博客,使用 pqi 来配置.那篇博客地址:

pip镜像管理和npm镜像管理

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.运行结果:

采用快恢复的:


使用快恢复

3.感想: 通过自己编程序模拟, 使得自己对TCP拥塞控制的机制更加熟悉。由于时间仓促,代码就还没进行优化,感兴趣的读者可以去优化一下. 感谢观看.

上一篇 下一篇

猜你喜欢

热点阅读