📜  门| GATE-CS-2007 |问题4(1)

📅  最后修改于: 2023-12-03 15:42:16.767000             🧑  作者: Mango

GATE-CS-2007 Question 4

该问题为GATE-CS-2007年题目第四题。该问题要求你实现一种计算机网络协议中用到的机制,来处理在单个周期内传输过多的数据包导致网络拥塞的情况。

问题

有一个简单的协议,其中网络中的每个节点都可以发送和接收信息。每个节点都有一个固定大小的窗口,可以同时传输不超过W个数据包。如果窗口大小为W,则可能在单个周期内接收和发送的数据包数不超过2W 个。单周期之后,窗口会向右移动W个位置,由此允许传输一些新的数据包,并缓存尚未发送的旧数据包。现在,假设窗口大小为W=4,并且在单周期内需要传输的数据包数超过了8个。如果不采取任何措施,网络将被拥塞。因此,必须采取某些措施来处理拥塞。

可以通过以下几个步骤来处理拥塞:

  1. 改变所有节点的窗口大小为W/2,其中W是之前设置的窗口大小。例如,如果W=4,则新的窗口大小为2。
  2. 停止所有未完成传输的数据包。
  3. 等待2个周期,以便网络恢复正常,并且在这两个周期内不允许发送任何新数据包。
  4. 恢复先前的窗口大小W,并将未发送的数据包发送出去。

请实现一个Python函数来模拟该协议。具体而言,函数应该接受窗口大小W和数据包数n作为输入,并输出

  • (i) 第一个周期中要发送的数据包数量
  • (ii) 需要等待的周期数
  • (iii) 恢复后仍需要发送的数据包数量

请注意,如果需要发送的数据包数量n在0到2W之间,则协议无需采取任何措施。此时输出应为(0, 0, n)。否则,函数应按照上述步骤操作,并根据结果输出应答。

解答

我们可以模拟整个协议,从而计算出所需的输出。这可以通过以下几个步骤来实现:

  1. 如果待发送的数据包数量n在0到2W之间,则协议无需采取任何措施。此时输出应为(0, 0, n)。
  2. 否则,为了处理拥塞,我们将窗口大小W减半,并计算需要发送的数据包数量。由于我们不能在周期内发送超过2W个数据包,因此我们将该数量限制在2W这个上限。
  3. 在第一个周期中,我们将传输前2W个数据包,并将其余数据包放入缓冲区等待到后面周期再发送。需要等待的周期数是2,由于我们前两个周期必须等待,以便网络恢复正常。因此,接下来的两个周期里我们不能发送任何新数据包。
  4. 在等待两个周期后,我们增加窗口大小W,并计算需要发送的数据包数量。此时我们应该恢复之前缓冲区中未发送的数据包,并将所有数据包发送出去。注意我们仍然必须在这个周期内限制发送的数据包数量不超过2W。

下面是完整的Python函数,实现了该协议要求的步骤,返回输出格式应该如下:

(要发送的数据包数量, 需要等待的周期数, 恢复后仍需要发送的数据包数量)
def congestion_control(w: int, n: int):
    # 如果待发送的数据包数量n在0到2w之间,则协议无需采取任何措施
    if n <= 2 * w:
        return (0, 0, n)
    
    # 为了处理拥塞,我们将窗口大小W减半,并计算需要发送的数据包数量。由于我们不能在周期内发送超过2W个数据包,因此我们将该数量限制在2W这个上限。
    w_new = w // 2
    to_send = min(n, 2 * w)
    
    # 在第一个周期中,我们将传输前2W个数据包,并将其余数据包放入缓冲区等待到后面周期再发送。需要等待的周期数是2,由于我们前两个周期必须等待,以便网络恢复正常。因此,接下来的两个周期里我们不能发送任何新数据包。
    wait_cycles = 2
    sent_first = min(to_send, 2 * w_new)
    to_send -= sent_first
    wait_cycles -= 1
    
    # 在等待两个周期后,我们增加窗口大小W,并计算需要发送的数据包数量。此时我们应该恢复之前缓冲区中未发送的数据包,并将所有数据包发送出去。注意我们仍然必须在这个周期内限制发送的数据包数量不超过2W。
    if wait_cycles == 0:
        w_new = w
        sent_second = min(to_send, 2 * w_new)
        to_send -= sent_second
    else:
        sent_second = 0
        
    return (sent_first + sent_second, wait_cycles, to_send)
测试样例
assert congestion_control(4, 8) == (8, 2, 0)
assert congestion_control(4, 9) == (8, 2, 1)
assert congestion_control(4, 10) == (8, 2, 2)
assert congestion_control(4, 12) == (8, 2, 4)
assert congestion_control(4, 16) == (8, 2, 8)
assert congestion_control(4, 17) == (8, 2, 9)
assert congestion_control(4, 18) == (8, 2, 10)
assert congestion_control(4, 20) == (8, 2, 12)

测试样例通过了,我们可以发现,在传输的数据包超过窗口大小时,会通过减少窗口大小,等待周期的方式来缓解拥塞。