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

数据块定义

在RUDP模块中,所有发送的数据被定义成RUDPRecvSegment 和 RUDPSendSegment结构,其中RUDPSendSegment是发送块定义,RUDPRecvSegment 是接收块定义。如下:

//发送数据片
typedef struct tagRUDPSendSegment
{
	uint64_t	seq_;                          //块序号
	uint64_t	push_ts_;		       //进入发送队列的时刻
	uint64_t	last_send_ts_;		       //最后一次发送的时刻
	uint16_t	send_count_;		       //发送的次数
	uint8_t		data_[MAX_SEGMENT_SIZE];       //块数据
	uint16_t	data_size_;                    //块数据长度
}RUDPSendSegment;
typedef struct tagRUDPRecvSegment
{
	uint64_t	seq_;                          //块序号
	uint8_t		data_[MAX_SEGMENT_SIZE];       //块数据
	uint16_t	data_size_;	               //块数据长度
}RUDPRecvSegment;

块的最大尺寸为MAX_SEGMENT_SIZE = 1408(不能大于MTU,一般MTU是1492)。为了加快内存分配的速度,RUDP模块中使用了对象池来保证块对象的快速申请,对象池定义:

ObjectPool<RUDPSendSegment, RUDP_SEGMENT_POOL_SIZE>	SENDSEGPOOL;
ObjectPool<RUDPRecvSegment, RUDP_SEGMENT_POOL_SIZE>	RECVSEGPOOL;

#define GAIN_SEND_SEG(seg) 	RUDPSendSegment* seg = SENDSEGPOOL.pop_obj();	seg->reset()

#define RETURN_SEND_SEG(seg) 	if(seg != NULL)		SENDSEGPOOL.push_obj(seg)

#define GAIN_RECV_SEG(seg) 	RUDPRecvSegment* seg = RECVSEGPOOL.pop_obj(); 	seg->reset()

#define RETURN_RECV_SEG(seg) 	if(seg != NULL)		RECVSEGPOOL.push_obj(seg)

几个宏是作为块申请和释放的宏。以上就是块的定义介绍,更具体的只有去查看相关源代码了。

发送缓冲区

发送缓冲区,定义如下:

class RUDPSendBuffer
{
public:
	...
	//发送数据接口
	int32_t				send(const uint8_t* data, int32_t data_size);
	//ACK处理
	void				on_ack(uint64_t ack_seq);
	//NACK处理
	void				on_nack(uint64_t base_seq, const LossIDArray& loss_ids);
	//定时器接口
	void				on_timer(uint64_t now_ts);
	//检查BUFFER是否可以写入数据
	void				check_buffer();
	...

public:
	uint64_t			get_buffer_seq() {return buffer_seq_;};
	//设置NAGLE算法
	void				set_nagle(bool nagle = true){nagle_ = nagle;};
	bool				get_nagle() const {return nagle_;};
	//设置发送缓冲区的大小
	void				set_buffer_size(int32_t buffer_size){buffer_size_ = buffer_size;};
	int32_t				get_buffer_size() const {return buffer_size_;};
	...

protected:
	IRUDPNetChannel*	net_channel_;

	//正在发送的数据片
	SendWindowMap		send_window_;
	//正在发送的报文的丢包集合
	LossIDSet			loss_set_;
	//等待发送的数据片
	SendDataList		send_data_;

	//发送缓冲区的大小
	int32_t				buffer_size_;
	//当前缓冲数据的大小
	int32_t				buffer_data_size_;
	//当前BUFFER中最大的SEQ
	uint64_t			buffer_seq_;
	//当前WINDOW中最大的SEQ
	uint64_t			cwnd_max_seq_;
	//接收端最大的SEQ
	uint64_t			dest_max_seq_;
	//速度控制器
	RUDPCCCObject*		ccc_;
	//是否启动NAGLE算法
	bool				nagle_;
}

其中send函数是数据写入函数,在这个函数里面,缓冲区对象先会对写入的数据进行报文拼接成发送块,让发送数据尽量接近MAX_SEGMENT_SIZE,如果发送的数据大于MAX_SEGMENT_SIZE,也会进行MAX_SEGMENT_SIZE为单元的分片。然后写入到对应的发送缓冲列表send_data_当中。最后尝试进行网络发送。伪代码如下:

int32_t RUDPSendBuffer::send(const uint8_t* data, int32_t data_size)
{
	int32_t copy_pos = 0;
	int32_t copy_size = 0;
	uint8_t* pos = (uint8_t *)data;
	uint64_t now_timer = CBaseTimeValue::get_time_value().msec();

	if(!send_data_.empty()) //拼接报文,让其接近MAX_SEGMENT_SIZE
	{
		//取出send_data_中的最后一片,如果它没有达到MAX_SEGMENT_SIZE,数据追加到MAX_SEGMENT_SIZE大小为止。
		RUDPSendSegment* last_seg = send_data_.back();
		if(last_seg != NULL && last_seg->data_size_ < MAX_SEGMENT_SIZE)
		{
			copy_size = MAX_SEGMENT_SIZE - last_seg->data_size_;
			if( copy_size > data_size)
				copy_size = data_size;

			memcpy(last_seg->data_ + last_seg->data_size_, pos, copy_size);

			copy_pos += copy_size;
			pos += copy_size;
			last_seg->data_size_ += copy_size;
		}
	}

	//剩余数据分成MAX_SEGMENT_SIZE为单位的若干分片
	while(copy_pos < data_size)
	{
		GAIN_SEND_SEG(last_seg);

		//设置初始化的的时刻
		last_seg->push_ts_ = now_timer; //记录压入时间戳
		last_seg->seq_ = buffer_seq_;
		buffer_seq_ ++;

		//确定拷贝的块长度
		copy_size = (data_size - copy_pos);
		if(copy_size > MAX_SEGMENT_SIZE)
			copy_size = MAX_SEGMENT_SIZE;

		memcpy(last_seg->data_, pos, copy_size);

		copy_pos += copy_size;
		pos += copy_size;
		last_seg->data_size_ = copy_size;
		//压入发送队列
		send_data_.push_back(last_seg);
	}

	//记录缓冲区的数据长度
	buffer_data_size_ += copy_pos;

	//尝试发送,立即发送
	attempt_send(now_timer);

	return copy_pos;
}

这里会触发attempt_send()函数。这个函数是尝试发送的核心函数。在后面的几个过程里面也会调用到这个函数。以上就是发送函数的过程。

时间: 2024-11-29 08:37:42

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

高性能服务框架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)算法详解(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