采用libuv搭建高并发tcp服务器,对于没有使用libuv经验,或者无并发服务器编写经验的朋友还是有一定难度的,通常面对的问题如下(以linux环境为前提):
1,并发服务器采用什么样的服务器模型?epoll?poll?还是select?
2,选择什么样的并发服务器框架?libevent?libev?还是libuv?
3,如果使用libuv作为服务器框架,其基础框架如何搭建
4,libuv对新手并不友好,尤其是处处回调,何时申请内存,何时释放内存?新手经常碰到内存释放不正确导致程序coredump
5,libuv中的async通知机制,即在其他线程写消息到主loop线程,据说会出现消息的合并通知,那如何设计来避免通知合并后,发送和接收端无法做到一一对应?
6,libuv给出的例子中,只单独给了tcp_echo和uv_queue_work的例子,如何把它们组合起来?
对于问题1:如果我们面对的客户端接入量只有几个,几十个,或者几百个,那么用select模型应该就能够满足需求,如果我们要面对几万,甚或者几十万的tcp连接,那么一定要采用epoll机制。对于poll不再讨论
对于问题2:选择什么样的并发框架,现在互联网上对libevent、libev、libuv对比的文章不少,大家可以多搜索多看看。最好是熟悉哪个就使用哪个,这样才能让你少走弯路。当然,对于喜欢折腾的人来说,熟悉其中2个或者三个都去学习学习,还是挺有意思。另外,如果选择libevent,建议去研究下memcached采用的线程模型,从那上面抽取出libevent的使用模型会更好一点
对于问题3-6,不做文字解答,套用linus的话:talk is cheap, show me the code!
#include <iostream>
#include <queue>
#include <map>
#include <set>
#include <unistd.h>
#include <stdlib.h>
#include <uv.h>
#include <string.h>
#include <time.h>
using namespace std;
uv_loop_t *loop;
uv_async_t async_send_msg;
queue<struct task> taskQueue;
pthread_mutex_t mutexTaskQueue = PTHREAD_MUTEX_INITIALIZER;
typedef struct {
uv_write_t req;
uv_buf_t buf;
} write_req_t;
struct task {
task():client(NULL),size(0){
memset(buffer,0,4097);
}
~task() {
}
uv_work_t req;
uv_stream_t* client;
uint8_t buffer[4096+1];
size_t size;
};
void free_write_req(uv_write_t *req) {
write_req_t *wr = (write_req_t*) req;
free(wr->buf.base);
free(wr);
}
void echo_w