C语言编写高并发Http文件上传下载服务器
前言
前段时间学习tinyhttpd和libevent开源库。
别人的代码写的再好终究是别人的,自以为看懂了,等到自己真正写的时候就会发现有各种问题。于是准备参考libevent里面最最最基础的功能(捡了芝麻丢了西瓜?),自己写一个event,用于熟悉libevent的I/O多路复用思想。然后再加上http。就有了这篇博客的Http高并发文件上传下载服务器(这里其实是伪高并发,下文会具体描述,原谅我的标题党,哈哈)。
共享代码给大家。希望可以帮助初学者熟悉http协议和libevent基础知识。如有问题,请大家不吝指出,谢谢!
项目效果图
- 服务器启动
- 使用客户端(浏览器)访问效果,这里是chrome
项目介绍
这里只是简单介绍下,具体细节请大家看代码,文章最后贴有代码地址。
环境介绍
系统平台:windows
开发工具:vs2010
开发语言:C
程序结构之:event相关
单线程,使用I/O多路复用实现并发。main函数进来后直接调用http_startup()。
int main()
{
UINT16 port = 80;
http_startup(&port);
return 0;
}
http_startup()里面创建一个socket用于listen,然后把这个socket扔到event里面,设置回调函数为accept_callback,等待客户端(这里就是各种浏览器)连接。所贴代码为了逻辑清晰,去掉了一些代码。
int http_startup(uint16_t *port)
{
SOCKET fd;
event_t ev = {
0};
network_listen(port, &fd);
ev.fd = fd;
ev.type = EV_READ | EV_PERSIST;
ev.callback = accept_callback;
event_add(&ev);
// dispatch里面就是个死循环,保证程序不退出
event_dispatch();
closesocket(fd);
return SUCC;
}
下面贴上event的核心,也就是event_dispatch()
为了逻辑清晰,也去掉了一些代码。
这里就是所谓的伪高并发之一了(后面还有之二):
由于是windows系统没有epoll,为了简单使用了select模型。尽管重新定义了FD_SETSIZE为1024,但是还是无关痛痒。1024个连接就满了,而且select是轮询机制,效率受限。
开始准备使用iocp,一来api的名字太难看了,就懒得研究了。二来我就是用来写个demo练练手,select也能凑合着用。
伪高并发之二:
网络I/O使用的是阻塞I/O,比如recv,会阻塞。上传文件时每次读取BUFFER_UNIT个数据,测试时log打印发现还是会偶尔阻塞一会。把BUFFER_UNIT改小的可能会有所改善,但是也不是解决办法。应该改成非阻塞I/O。这里也不讨论这个问题了。
#define BUFFER_UNIT 4096
ret_code_t event_dispatch()
{
fd_set readfds;
fd_set writefds;
fd_set exceptfds;
struct timeval timeout = {
0, 500000 };
int ret;
uint32_t i;
while