高性能服务框架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中的数据
	int32_t				read(uint8_t* data, int32_t data_size);
	//检查缓冲区是否可读
	void				check_buffer();
	//检查丢包
	bool				check_loss(uint64_t now_timer, uint32_t rtc);
	...
protected:
	IRUDPNetChannel*	net_channel_;
	//接收窗口
	RecvWindowMap		recv_window_;
	//已完成的连续数据片
	RecvDataList		recv_data_;
	//丢包序列
	LossIDTSMap			loss_map_;
	//当前BUFFER中最大连续数据片的SEQ
	uint64_t			first_seq_;
	//当期BUFFER中受到的最大的数据片ID
	uint64_t			max_seq_;
	//最后一次发送ACK的时刻
	uint64_t			last_ack_ts_;
	//在上次发送ACK到现在,受到新的连续报文的标志
	bool				recv_new_packet_;
	...
};

在上面定义中,核心的函数主要是on_data和on_timer。on_data是接收来自发送端的RUDP数据报文,在这个函数里面首先会进行接收到报文和缓冲去里面的报文进行比较判断是否丢包和重复包。如果有丢包,记录到loss_map中。如果是重复包,则丢弃。如果接收到的包和缓冲区里的报文可以组成连续的块序列。则对上层触发on_read读事件。一下是这个函数的伪代码:

int32_t RUDPRecvBuffer::on_data(uint64_t seq, const uint8_t* data, int32_t data_size)
{
	//报文合法性检测
	if(seq > first_seq_ + MAX_SEQ_INTNAL || data_size > MAX_SEGMENT_SIZE)
	{
		//报告异常
		RUDP_RECV_DEBUG("on data exception!!");
		net_channel_->on_exception();
		return -1;
	}

	RUDPRecvSegment* seg = NULL;
	if(first_seq_ + 1 == seq)//连续报文
	{
		recv_new_packet_= true;
		//将数据缓冲到队列中
		GAIN_RECV_SEG(seg);
		seg->seq_ = seq;
		seg->data_size_ = data_size;
		memcpy(seg->data_, data, data_size);
		recv_data_.push_back(seg);

		first_seq_ = seq;
		//判断缓冲区中的块是否连续,并进行排序
		check_recv_window();
		//触发可读事件
		net_channel_->on_read();

		//删除丢包
		loss_map_.erase(seq);
	}
	else if(seq > first_seq_ + 1) //非连续报文
	{
		RecvWindowMap::iterator it = recv_window_.find(seq);
		if(it == recv_window_.end()) //记录到接收窗口中
		{
			//将数据缓冲到队列中
			GAIN_RECV_SEG(seg);
			seg->seq_ = seq;
			seg->data_size_ = data_size;
			memcpy(seg->data_, data, data_size);

			recv_window_[seq] = seg;
		}

		//判断丢包
		if(seq > max_seq_ + 1)
		{
			uint64_t ts = CBaseTimeValue::get_time_value().msec();
			for(uint64_t i = max_seq_ + 1; i < seq;  ++ i) //缓冲区中最大的报文和收到的报文之间的报文全部列入丢包范围中,并记录丢包时刻
				loss_map_[i] = ts;
		}
		else
		{
			//删除丢包
			loss_map_.erase(seq);
		}
	}
	//更新缓冲区最大SEQ
	if(max_seq_ < seq)
		max_seq_ = seq;
	return 0;
}

on_timer是定时触发的,一般是5MS触发一次。主要是向发送端发送报告消息(ack/nack)、检查缓冲区是否可读两个操作。发送ack状态消息的条件是

uint32_t rtc_threshold = core_min(20, rtc / 2);

发送ack

其中rtc是RTT的修正值,由CCC计算得来。间隔不大于20MS发送一次。recv_new_packet_是一个收到正常连续报文的标志。如果发送了NACK,就不发送ACK,如果有丢包的话,就会触发发送nack,在on_timer的时候就会检测是本定时周期是否有丢包,如果有,就将丢包的序号通过nack发往发送端做丢包补偿。

void RUDPRecvBuffer::on_timer(uint64_t now_timer, uint32_t rtc)
{       //检查丢包
	if(check_loss(now_timer, rtc))
		recv_new_packet_ = false;
	//检查是否需要发送ack
	uint32_t rtc_threshold = core_min(20, rtc / 2);
	if(last_ack_ts_ + rtc_threshold <= now_timer && recv_new_packet_)
		send_ack();

	//检查缓冲区是否可读
	if(!recv_data_.empty() && net_channel_ != NULL)
		net_channel_->on_read();
}

CCC核心控制

CCC的核心控制就是慢启动、快恢复、RTT评估三个部分。

慢启动过程描述如下:

1、发送端的初始化发送窗口(send_wnd)为16

2、当发送端收到第一个ACK时,send_wnd = send_wnd + (本ACK周期内发送成功的报文数量)

时间: 2024-07-28 12:27:56

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

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

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

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

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

使用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