高性能服务框架revolver:RUDP(可靠UDP)算法详解(2)

除了发送函数以外,发送缓冲区对象还会响应来自网络的on_ack和on_nack消息,这两个消息分别是处理正常的状态报告和丢包情况下的网络报告。如果收到on_ack,缓冲区对象会把已经接收端报告过来的报文ID全部从发送窗口中删除,然后调用attempt_send尝试新的块发送。如果收到的是on_nack,表示对端有丢包,则先会记录丢包的ID到loss_set中,再调用on_ack进行处理。

触发attempt_send还有可能是定时器Timer,定时器每5MS会检查一下发送缓冲区,并调用attempt_send尝试发送并且会检查缓冲区是否可写。

attempt_send函数伪代码如下:

void RUDPSendBuffer::attempt_send(uint64_t now_timer)
{
	uint32_t cwnd_size = send_window_.size();
	uint32_t rtt = ccc_->get_rtt();
	uint32_t ccc_cwnd_size = ccc_->get_send_window_size();
	RUDPSendSegment* seg = NULL;

	uint32_t send_packet_number  = 0;
	if(!loss_set_.empty()) //重发丢失的片段
	{
		//发送丢包队列中的报文
		uint64_t loss_last_ts = 0;
		uint64_t loss_last_seq = 0;
		for(LossIDSet::iterator it = loss_set_.begin(); it != loss_set_.end();) //检查丢失报文是否要重发
		{
			if(send_packet_number >= ccc_cwnd_size) //超过发送窗口
				break;

			SendWindowMap::iterator cwnd_it = send_window_.find(*it);
			if(cwnd_it != send_window_.end() && cwnd_it->second->last_send_ts_ + rtt < now_timer) //丢失报文必须在窗口中
			{
				seg = cwnd_it->second;
				//UDP网络发送
				net_channel_->send_data(0, seg->seq_, seg->data_, seg->data_size_, now_timer);
				if(cwnd_max_seq_ < seg->seq_)
					cwnd_max_seq_ = seg->seq_;

				//判断是否可以更改TS
				if(loss_last_ts < seg->last_send_ts_)
				{
					loss_last_ts = seg->last_send_ts_;
					if(loss_last_seq < *it)
						loss_last_seq = *it;
				}

				seg->last_send_ts_ = now_timer;
				seg->send_count_ ++;

				send_packet_number ++;

				loss_set_.erase(it ++);
				//报告CCC有重发
				ccc_->add_resend();

			}
			else
				++ it;
		}
		//更新重发包范围内未重发报文的时刻,防止下一次定时器到来时重复发送
		for(SendWindowMap::iterator it = send_window_.begin(); it != send_window_.end(); ++it)
		{
			if(it->second->push_ts_ < loss_last_ts && loss_last_seq >= it->first)
				it->second->last_send_ts_ = now_timer;
			else if(loss_last_seq < it->first)
				break;
		}
	}
	else if(send_window_.size() > 0)//丢包队列为空,重发所有窗口中超时的分片
	{
		//发送间时间隔阈值
		uint32_t rtt_threshold = (uint32_t)ceil(rtt * 1.25);
		rtt_threshold = (core_max(rtt_threshold, 30));

		SendWindowMap::iterator end_it = send_window_.end();
		for(SendWindowMap::iterator it = send_window_.begin(); it != end_it; ++it)
		{
			if(send_packet_number >= ccc_cwnd_size || (it->second->push_ts_ + rtt_threshold > now_timer))
				break;

			seg = it->second;

			//重发块的触发条件是上一次发送的时间距离现在大于特定的阈值或者压入时间很长并且是属于发送缓冲区靠前的块
			if(seg->last_send_ts_ + rtt_threshold < now_timer
				|| (seg->push_ts_ + rtt_threshold * 5 < now_timer && seg->seq_ < dest_max_seq_ + 3 && seg->last_send_ts_ + rtt_threshold / 2 < now_timer))
			{
				net_channel_->send_data(0, seg->seq_, seg->data_, seg->data_size_, now_timer);

				if(cwnd_max_seq_ < seg->seq_)
					cwnd_max_seq_ = seg->seq_;

				seg->last_send_ts_ = now_timer;
				seg->send_count_ ++;

				send_packet_number ++;
				//报告CCC有重发块
				ccc_->add_resend();
			}
		}
	}
	//判断是否可以发送新的报文
	if(ccc_cwnd_size > send_packet_number)
	{
		while(!send_data_.empty())
		{
			RUDPSendSegment* seg = send_data_.front();
			//判断NAGLE算法,NAGLE最少需要在100MS凑1024个字节报文
			if(cwnd_size > 0 && nagle_ && seg->push_ts_ + NAGLE_DELAY > now_timer && seg->data_size_ < MAX_SEGMENT_SIZE - 256)
				break;

			//判断发送窗口
			if(cwnd_size < ccc_cwnd_size)
			{
				send_data_.pop_front();
				send_window_.insert(SendWindowMap::value_type(seg->seq_, seg));
				cwnd_size ++;

				seg->push_ts_ = now_timer;
				seg->last_send_ts_ = now_timer;
				seg->send_count_ = 1;
				//UDP网络发送
				net_channel_->send_data(0, seg->seq_, seg->data_, seg->data_size_, now_timer);
				if(cwnd_max_seq_ < seg->seq_)
					cwnd_max_seq_ = seg->seq_;
			}
			else //发送窗口满,则停止发送
				break;
		}
	}
}

从上可得知,attempt_send是首先检查是否可以发送丢失的报文,然后再检查窗口中太老的报文是否要重发,最后才加入新的发送报文。所有的前提约束是不超过发送窗口。这个函数里CCC决定的发送窗口大小和RTT直接控制着发送速度和发送策略。 在这里值得一提的是NAGLE的实现,RUDP为了防止小包过多,实现了一个nagle算法,如果设置了此开关,假如只有1个块在缓冲队列中,会等数据达到1024的长度才进行发送。如果等100MS没到1024长度也会发送,也就是最大等100MS.开关可以通过rudp interface设置的。

接收缓冲区

时间: 2024-10-08 12:43:22

高性能服务框架revolver:RUDP(可靠UDP)算法详解(2)的相关文章

高性能服务框架revolver:RUDP(可靠UDP)算法详解

数据块定义 在RUDP模块中,所有发送的数据被定义成RUDPRecvSegment 和 RUDPSendSegment结构,其中RUDPSendSegment是发送块定义,RUDPRecvSegment 是接收块定义.如下: //发送数据片 typedef struct tagRUDPSendSegment { uint64_t seq_; //块序号 uint64_t push_ts_; //进入发送队列的时刻 uint64_t last_send_ts_; //最后一次发送的时刻 uint1

高性能服务框架revolver:RUDP(可靠UDP)算法详解(3)

接收缓冲区相对比较简单,其主要功能是接收发送方的数据并生成接收块.块排序.丢包判断和反馈.读事件通知等.以下是接收缓冲区的定义: class RUDPRecvBuffer { public: ... //来自网络中的数据 int32_t on_data(uint64_t seq, const uint8_t* data, int32_t data_size); //定时事件 void on_timer(uint64_t now_timer, uint32_t rtc); //读取BUFFER中的

使用ssh开发rest web服务支持http etag header的教程详解

原创整理不易,转载请注明出处:使用ssh开发rest web服务支持http etag header的教程详解 代码下载地址:http://www.zuidaima.com/share/1777391667989504.htm 导言 REST方式的应用程序构架在近日所产生的巨大影响突出了Web应用程序的优雅设计的重要性.现在人们开始理解"WWW架构"内在的可测量性及弹性,并且已经开始探索使用其范例的更好的方式.在本文中,我们将讨论一个Web应用开发工具--"简陋的.卑下的&q

安全体系(二)——RSA算法详解

本文主要讲述RSA算法使用的基本数学知识.秘钥的计算过程以及加密和解密的过程. 安全体系(零)—— 加解密算法.消息摘要.消息认证技术.数字签名与公钥证书 安全体系(一)—— DES算法详解 1.概述 RSA公钥加密算法是1977年由罗纳德·李维斯特(Ron Rivest).阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的.1987年首次公布,当时他们三人都在麻省理工学院工作.RSA算法以他们三人姓氏开头字母命名. RSA是目前最有影响力的公钥加密

java UDP传输详解

UDP传输是一个面向无连接的传输方式,什么叫无连接呢,简单点说呢就是不管你在不在线,我都发数据给你,像那个电影里警察拿的那个呼叫用的就这这个原理 还有以前的QQ聊天也是,现在2013版的可以选择是UPD还是TCP,好了不多说,上点代码玩一下 分析:通过udp传输方式,将一段数据发送出去 思路: 1,建议udpsocket服务 2,提供数据,并将数据封装到数据包中 3,通过socket服务的发送功能,讲数据包发送出去. 4,关闭资源 牢记思路,代码哪里都有 package com.szc02; i

【目标检测】Faster RCNN算法详解

Ren, Shaoqing, et al. "Faster R-CNN: Towards real-time object detection with region proposal networks." Advances in Neural Information Processing Systems. 2015. 本文是继RCNN[1],fast RCNN[2]之后,目标检测界的领军人物Ross Girshick团队在2015年的又一力作.简单网络目标检测速度达到17fps,在P

风螺旋公切线算法详解

风螺旋公切线算法详解 2017-12-29 刘崇军 风螺旋线 好久不见,近来一切可好?2017年最后这段时间里,狂补了一把C#,希望未来能够从软件代码层面实现风螺旋算法的验证与推广.今天跟大家分享的这个话题的底图就是最近一段时间的学习成果:一个基于WPF架构的非常简单的绘图框架,以及对风螺旋的自动化绘制进行的实现.闲话少叙,开始今天的主题. 在掌握了风螺旋切线计算的基础上,就可以开始公切线算法的研究了.公切线的计算是飞行程序模板中非常关键的一项内容,因此,在开始模板算法分享之前,详细回顾一下公切

第二十八节,目标检测算法之R-CNN算法详解

Girshick, Ross, et al. "Rich feature hierarchies for accurate object detection and semantic segmentation." Proceedings of the IEEE conference on computer vision and pattern recognition. 2014. R-CNN的全称是Region-CNN,它可以说是第一个成功将深度学习应用到目标检测上的算法.后面要讲到的

5. 目标检测算法之R-CNN算法详解(转)

5. 目标检测算法之R-CNN算法详解(转) 原文链接:https://www.cnblogs.com/zyly/p/9246221.html 目录 一 R-CNN思路 二 算法简述 三 训练步骤 四 优缺点 Girshick, Ross, et al. "Rich feature hierarchies for accurate object detection and semantic segmentation." Proceedings of the IEEE conferenc