Revolver源码解析之——RUDP发送速率控制器

1、功能:实现带宽评估、发送窗口决策、RTT与RTC的计算。

2、成员函数解析。

[1].处理接收到的ACK。

void RUDPCCCObject::on_ack(uint64_t ack_seq)
{
	if(ack_seq <= last_ack_id_)
	{
		return;
	}
	 
	uint32_t space = (uint32_t)(ack_seq - last_ack_id_);
	if(slow_start_) //慢启动窗口决策
	{
		snd_cwnd_ += space;
		if(snd_cwnd_ >= max_cwnd_)
		{
			slow_start_ = false;
			RUDP_INFO("ccc stop slow_start, snd_cwnd = " << snd_cwnd_);

			snd_cwnd_ = max_cwnd_;
		}

		RUDP_DEBUG("send window size = " << snd_cwnd_);
	}

	//RUDP_DEBUG("onack, seq = " << ack_seq);
	last_ack_id_ = ack_seq;
}

首先检查ACK的ID的合法性,若ACK的ID是非法的,则不处理当前ACK。否则,启动慢窗口决策并更新zui最新收到的ACK包的ID。

[2].处理接收到的nack。

void RUDPCCCObject::on_loss(uint64_t base_seq, const LossIDArray& loss_ids)
{
	if(slow_start_) //取消慢启动
	{
		slow_start_ = false;
		RUDP_INFO("ccc stop slow_start, snd_cwnd = " << snd_cwnd_);
	}
}

这里主要是取消慢启动策略。

[3].设置滑动窗口的最大尺寸。

void RUDPCCCObject::set_max_cwnd(uint32_t rtt)
{ 
	if (rtt < 10) //吞吐量上限设置
		max_cwnd_ = 512;
	else if (rtt < 50)
		max_cwnd_ = 1024;
	else if (rtt < 100)
		max_cwnd_ = 1024 + 256;
	else if (rtt <= 200)
		max_cwnd_ = 1024 + 512;
	else{
		max_cwnd_ = 1024;
	}


	limit_cwnd_ = 128;
}   

这里主要是依据rtt的值来计算发送方滑动窗口的最大值,同时将发送方滑动窗口的最小值设置为128 。

[4].速率控制器的定时事件。

void RUDPCCCObject::on_timer(uint64_t now_ts)
{
    //delay 不小于 100ms
	uint32_t delay = core_max(rtt_ * 4, 100);
	if (now_ts >= prev_on_ts_ + delay) //10个RTT决策一次
	{
		print_count_ ++;
		if(print_count_ % 4 == 0)
		{
			set_max_cwnd(rtt_);
		}

		if(slow_start_) //停止慢启动过程
        {
			if(print_count_ > 10)
			{
				slow_start_ = false;
				RUDP_INFO("ccc stop slow_start, snd_cwnd = " << snd_cwnd_);
			}

		}
		else
		{
			if (recv_count_ / 16 > resend_count_)
			{
				snd_cwnd_ = (uint32_t)(snd_cwnd_ + core_max(8, (snd_cwnd_ / 8)));
				snd_cwnd_ = core_min(max_cwnd_, snd_cwnd_);
			}
			else if (recv_count_ / 4 < resend_count_){
				snd_cwnd_ = (uint32_t)(snd_cwnd_ - (snd_cwnd_ / 4));
				snd_cwnd_ = core_max(min_cwnd_, snd_cwnd_);
				loss_flag_ = true;

				if (snd_cwnd_ < limit_cwnd_)
					min_cwnd_ = limit_cwnd_;
			}
		
			RUDP_DEBUG("send window size = " << snd_cwnd_ << ",rtt = " << rtt_ << ",rtt_var = " << rtt_var_ << ",resend = " << resend_count_ << "recv count = " << recv_count_);

			resend_count_ = 0;
			recv_count_ = 0;
		}
		prev_on_ts_ = now_ts;
		loss_flag_ = false;
	} 
}

 此成员函数实现慢启动、发送窗口动态调整决策。这个成员函数每四个delay时间段调整最大发送窗口与最小发送窗口,初始时,是十个delay之前是慢启动的过程,十个delay之后是动态调整发送窗口的尺寸并更新最小发送窗口。若在在这段时间内(10个delay),接收数据片的数量是重发的数据片的数量的16倍以上,则扩大滑动窗口。

			if (recv_count_ / 16 > resend_count_)
			{
				snd_cwnd_ = (uint32_t)(snd_cwnd_ + core_max(8, (snd_cwnd_ / 8)));
				snd_cwnd_ = core_min(max_cwnd_, snd_cwnd_);
			}

若接收 数据片的数量/重发数据片的数量<4,则缩小滑动窗口的尺寸。并更新滑动窗口的最小值。

			else if (recv_count_ / 4 < resend_count_){
				snd_cwnd_ = (uint32_t)(snd_cwnd_ - (snd_cwnd_ / 4));
				snd_cwnd_ = core_max(min_cwnd_, snd_cwnd_);
				loss_flag_ = true;
                
                if (snd_cwnd_ < limit_cwnd_)
					min_cwnd_ = limit_cwnd_;
			}

重置接收数据片与重发的数据片的数量。之后是每过一个delay就要动态调整发送窗口的尺寸并更新最小发送窗口。

[5].设置rtt_(往返时延)与rtt_var_(一个数据片从发送端发送到接收端接收的时间)。

void RUDPCCCObject::set_rtt(uint32_t keep_live_rtt)
{
	//提高高延迟网络的吞吐量(BDP)
	if(max_cwnd_ == DEFAULT_CWND_SIZE)
		set_max_cwnd(keep_live_rtt);

	//计算rtt和rtt修正
	if(rtt_first_)
	{
		rtt_first_ = false;
		rtt_ = keep_live_rtt;
		rtt_var_ = rtt_ / 2;
	}
	else //参考了tcp的rtt计算
	{
		rtt_var_ = (rtt_var_ * 3 + core_abs(rtt_, keep_live_rtt)) / 4;
		rtt_ = (7 * rtt_ + keep_live_rtt) / 8;
	}

    //rtt_与rtt_var_不能小于1ms
	rtt_ = core_max(1, rtt_);
	rtt_var_ = core_max(1, rtt_var_);
}

设置rtt。首次计算时,

	//计算rtt和rtt修正
	if(rtt_first_)
	{
		rtt_first_ = false;
		rtt_ = keep_live_rtt;
		rtt_var_ = rtt_ / 2;
	}

即将keep_live_rtt赋值给rtt_,将keep_alive_rtt的一半赋值给rtt_var_。

以后的rtt_与rtt_var_的计算则参考了TCP。

	else //参考了tcp的rtt计算
	{
		rtt_var_ = (rtt_var_ * 3 + core_abs(rtt_, keep_live_rtt)) / 4;
		rtt_ = (7 * rtt_ + keep_live_rtt) / 8;
	}

rtt_var_=3/4rtt_var_+1/4abs(rtt_-keep_live_rtt);

  rtt_=7/8rtt+1/8(keep_live_rtt)


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值