libevent实现文件服务器

2 篇文章 0 订阅

使用libevent实现高速文件服务.

当收到HTTP请求后, 启动文件发送作业:

	// 定义数据结构.
	typedef struct http_file_sender_t http_file_sender_t;
	struct http_file_sender_t
	{
		struct evhttp_request* req;	///< http请求句柄
		struct evbuffer* evb;		///< 数据缓存
		int fd;						///< 文件句柄
		int eof;			///< 是否到达文件尾
		int64_t start_time;		///< 开始发送的时间.
		ssize_t data_offset;		///< 数据块偏移位置.
		ssize_t data_bytes;			///< 从文件读取的数据长度
		size_t data_cache_size;	///< data_cache 的长度
		size_t length;	///< 总长度.
		char* data_cache;			///< 数据块缓存. 最大长度为 FILE_CACHE_SIZE
		char* filename;		///< 文件名.
	};

	// 准备文件发送任务.
	http_file_sender_t* sender;
	sender= (mdf_http_file_sender_t*)malloc(sizeof(mdf_http_file_sender_t));
	sender->evb = evbuffer_new();
	sender->fd = fd;
	sender->req = req;
	sender->data_bytes = 0L;
	sender->data_offset = 0L;
	sender->eof = FALSE;
	// range_start和range_end分别是文件要发送数据的开始和结束位置
	sender->length = range_end - range_start;
	sender->start_time = start_time;
	sender->filename = strdup(url);

	// cache最大限定 (默认4MB)
	if (sender->length > FILE_CACHE_SIZE)
	{
		sender->data_cache_size = FILE_CACHE_SIZE;
	}
	else
	{
		sender->data_cache_size = sender->length;
	}

	sender->data_cache = (char*)malloc(sender->data_cache_size);
	assert(sender->data_cache);

	lseek(fd, (off_t)range_start, SEEK_SET);

	// 开始发送数据
	if (range_start > 0L)
	{
		evhttp_send_reply_start(req, 206, "Partial Content");
	}
	else
	{
		evhttp_send_reply_start(req, HTTP_OK, NULL);
	}

// 发送数据
	http_file_send_chunk(NULL, sender);

其中http_file_send_chunk函数:


static void http_file_send_chunk(struct evhttp_connection* conn, void* arg)
{
	http_file_sender_t* sender = arg;
	// 没有数据就要读取.
	if (sender->data_offset >= sender->data_bytes)
	{
		if (sender->eof)
		{
			http_file_sender_close(sender);
			return;
		}

		// 从文件读取数据.
		sender->data_bytes = read(sender->fd, sender->data_cache, sender->data_cache_size);
		if (sender->data_bytes <= 0)
		{
			http_file_sender_close(sender);
			return;
		}

		// 如果读取的长度不足一个CHUNK长度, 则任务已读完所有数据.
		if (sender->data_bytes < FILE_CACHE_SIZE)
		{
			sender->eof = TRUE;
		}
		// 从0开始.
		sender->data_offset = 0L;
	}

	if (sender->data_offset + FILE_CHUNK_SIZE <= sender->data_bytes)
	{
		evbuffer_add_reference(sender->evb,
			sender->data_cache + sender->data_offset,	// data
			FILE_CHUNK_SIZE,		// size
			NULL, NULL);
		sender->data_offset += FILE_CHUNK_SIZE;
	}
	else
	{
		evbuffer_add_reference(sender->evb,
			sender->data_cache + sender->data_offset,	// data
			(size_t)(sender->data_bytes - sender->data_offset),	// size
			NULL, NULL);
		sender->data_offset = sender->data_bytes;
	}
	assert(evhttp_request_get_connection(sender->req));
	evhttp_send_reply_chunk_with_cb(sender->req, sender->evb, &mdf_http_file_send_chunk, sender);
}

一个HTTP服务线程可同时支持多个文件下载任务

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值