在 TCP Reno 中找到最终拥塞窗口大小的程序
给定初始拥塞窗口大小cwnd、阈值ssthresh、连接时间rtt和数组arr ,其中 arr[i] 表示检测到数据包丢失的时间。任务是在发送方遇到所有丢包时找到最终的拥塞窗口大小。
The TCP Reno follows below conditions:
- The initial value of cwnd is 1.
- Before reaching ssthresh, double cwnd per unit of time. By doubling the value, cwnd can’t cross ssthresh value, it can almost go up to ssthresh value.
- After reaching ssthresh, increase cwnd by 1 per unit of time.
- When there is packet loss, reduce the cwnd and ssthresh to half of cwnd value (50%) and no other updation happens.
- Connection will be active until rtt unit of time.
例子:
Input arr[] = {16, 22}, ssthresh = 32, rtt = 26
Output: 17
Explanation:
Time = 0: cwnd = 1
Time = 1: cwnd = 2
Time = 2, 3, 4, 5: cwnd = 4, 8, 16, 32
cwnd=ssthresh at time=5, so now onwards cwnd increases by 1 per unit of time.
Time = 6-15: cwnd = 33-42
Time = 16: packet loss is detected, so ssthresh and cwnd will become half of current cwnd value.
cwnd = ssthresh = 21, Note: cwnd is not increased by 1 or doubled in this case.
Time = 17-21: cwnd = 22-26
Time = 22: packet loss is detected, so ssthresh and cwnd will become half of current cwnd value.
cwnd = ssthresh = 13
Time = 23-26: cwnd = 14-17
Final cwnd is = 17
Input arr[] = {12, 25, 37, 42}, ssthresh = 30, rtt = 50
Output: The final cwnd value is= 16
Explanation:
Time = 0: cwnd = 1
Time = 1: cwnd = 2
Time = 2, 3, 4: cwnd = 4, 8, 16
Time = 5: cwnd = 30 {cwnd can’t get doubled because 32>30, it will cross the ssthresh. It can go max upto ssthresg}
Time = 6-11: cwnd = 31-36
Time = 12: cwnd = 36/2 and ssthresh = 18 {Packet loss}
Time = 13-24: cwnd = 19-30
Time = 25: cwnd = ssthresh = 30/2 = 15 {Packet loss}
Time = 26-36: cwnd = 16-26
Time = 37: cwnd = ssthresh = 26/2 = 13 {Packet loss}
Time = 38-41: cwnd = 14-17
Time = 42: cwnd = ssthresh = 17/2 = 8 {Packet loss}
Time = 43-50: cwnd = 9-16
The final cwnd value is= 16
方法:解决方案基于cwnd和ssthresh 值的比较。按照以下步骤操作:
- 当连接处于活动状态时,遍历所有时间单位。
- 将下一个丢包时间存储在可变超时中
- 检查当前时间是否等于超时。如果是,则减少cwnd和ssthresh = cwnd/2
- 如果cwnd小于ssthresh ,则将 cwnd 值加倍。
- 如果cwnd的两倍大于ssthresh ,则设置cwnd=ssthresh。
- 如果cwnd大于ssthresh ,则每次将cwnd 增加 1 。
- 循环终止后返回最终的 cwnd 值。
下面是上述方法的实现。
C++
// C++ code to implement the approach
#include
using namespace std;
// TCP Reno Utility function
int tcpRenoCongestionWindow(int cwnd,
int ssthresh, int rtt,
vector time)
{
int ind = 0, timeout = time[ind];
for (int t = 1; t <= rtt; t++) {
// Packet loss occurs.
// Reduce cwnd and ssthresh to
// half of current cwnd value
if (t == timeout) {
cwnd = cwnd / 2;
ssthresh = cwnd;
timeout = time[++ind];
continue;
}
// Threshold is not reached.
// keep doubling
if (cwnd < ssthresh)
cwnd = min(2 * cwnd, ssthresh);
// Threshold is reached.
// Increase additively.
else
cwnd += 1;
}
// Return final cwnd value.
return cwnd;
}
// Driver code
int main()
{
int cwnd = 1;
int ssthresh = 30;
int rtt = 50;
vector time{ 12, 25, 37, 42 };
cwnd = tcpRenoCongestionWindow(cwnd, ssthresh, rtt,
time);
cout << "Final congestion window size = " << cwnd;
return 0;
}
Java
// Java code to implement the approach
import java.util.*;
public class GFG {
// TCP Reno Utility function
static int tcpRenoCongestionWindow(int cwnd,
int ssthresh,
int rtt, int[] time)
{
int ind = 0, timeout = time[ind];
for (int t = 1; t <= rtt; t++) {
// Packet loss occurs.
// Reduce cwnd and ssthresh to
// half of current cwnd value
if (t == timeout) {
cwnd = cwnd / 2;
ssthresh = cwnd;
ind += 1;
if (ind == time.length) {
continue;
}
timeout = time[ind];
continue;
}
// Threshold is not reached.
// keep doubling
if (cwnd < ssthresh)
cwnd = Math.min(2 * cwnd, ssthresh);
// Threshold is reached.
// Increase additively.
else
cwnd += 1;
}
// Return final cwnd value.
return cwnd;
}
// Driver code
public static void main(String args[])
{
int cwnd = 1;
int ssthresh = 30;
int rtt = 50;
int[] time = { 12, 25, 37, 42 };
cwnd = tcpRenoCongestionWindow(cwnd, ssthresh, rtt,
time);
System.out.print("Final congestion window size = "
+ cwnd);
}
}
// This code is contributed by Samim Hossain Mondal.
Python3
# Python 3 code to implement the approach
# TCP Reno Utility function
def tcpRenoCongestionWindow(cwnd,
ssthresh, rtt, time):
ind = 0
timeout = time[ind]
for t in range(1, rtt + 1):
# Packet loss occurs.
# Reduce cwnd and ssthresh to
# half of current cwnd value
if (t == timeout):
cwnd = cwnd // 2
ssthresh = cwnd
ind += 1
if(ind == len(time)):
continue
timeout = time[ind]
continue
# Threshold is not reached.
# keep doubling
if (cwnd < ssthresh):
cwnd = min(2 * cwnd, ssthresh)
# Threshold is reached.
# Increase additively.
else:
cwnd += 1
# Return final cwnd value.
return cwnd
# Driver code
if __name__ == "__main__":
cwnd = 1
ssthresh = 30
rtt = 50
time = [12, 25, 37, 42]
cwnd = tcpRenoCongestionWindow(cwnd, ssthresh, rtt,
time)
print("Final congestion window size = ", cwnd)
# This code is contributed by ukasp.
C#
// C# code to implement the approach
using System;
class GFG {
// TCP Reno Utility function
static int tcpRenoCongestionWindow(int cwnd,
int ssthresh,
int rtt, int[] time)
{
int ind = 0, timeout = time[ind];
for (int t = 1; t <= rtt; t++) {
// Packet loss occurs.
// Reduce cwnd and ssthresh to
// half of current cwnd value
if (t == timeout) {
cwnd = cwnd / 2;
ssthresh = cwnd;
ind += 1;
if (ind == time.Length) {
continue;
}
timeout = time[ind];
continue;
}
// Threshold is not reached.
// keep doubling
if (cwnd < ssthresh)
cwnd = Math.Min(2 * cwnd, ssthresh);
// Threshold is reached.
// Increase additively.
else
cwnd += 1;
}
// Return final cwnd value.
return cwnd;
}
// Driver code
public static void Main()
{
int cwnd = 1;
int ssthresh = 30;
int rtt = 50;
int[] time = { 12, 25, 37, 42 };
cwnd = tcpRenoCongestionWindow(cwnd, ssthresh, rtt,
time);
Console.Write("Final congestion window size = "
+ cwnd);
}
}
// This code is contributed by Samim Hossain Mondal.
Javascript
Final congestion window size = 16
时间复杂度: O(N),N是连接活跃的时间。
辅助空间: O(1)