libevent 服务器的简单实现
libevent是一款非常轻量级的网络库,好用到手软。客户端实现参考这里。废话不多,直接开撸!
libevent 重要部件
event_base: 负责调度event事件
event: 各个监控事件
event_base_dispatch: 启动监控!
三者之间的关系
event_base 相当于一个监控器,可以把各种需要监控的event事件放到监控器中,event_base_dispatch就是一键启动按钮。
值得注意的是,在启动之后,还可以向event_base中添加event。如下面例子中的bufferevent。
废话不多,直接上码
/*
* sample for learning
* */
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define LE_ADDRESS_SIZE 32
#define LE_BUFFER_SIZE 1024
typedef struct event_base EventBase;
typedef struct event Event;
void readcb(struct bufferevent *bev, void *arg)
{
char buf[LE_BUFFER_SIZE];
size_t n = bufferevent_read(bev, buf, LE_BUFFER_SIZE - 1);
buf[n] = '\0';
printf("%s\n", buf);
}
void eventcb(struct bufferevent *bev, short flag, void *arg)
{
if(flag & BEV_EVENT_EOF)
{
printf("remote peer closed\n");
}
else if(flag & BEV_EVENT_ERROR)
{
}
else if (flag & BEV_EVENT_TIMEOUT)
{
}
bufferevent_free(bev);
}
// event callback
void acceptcb(struct evconnlistener *listener, evutil_socket_t fd,
struct sockaddr *addr, int socklen, void *arg)
{
EventBase *base = (EventBase *)arg;
struct sockaddr_in *sin = (struct sockaddr_in *)addr;
printf("connection from %s:%d\n", inet_ntoa(sin->sin_addr), ntohs(sin->sin_port));
struct bufferevent *bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);
bufferevent_setcb(bev, readcb, NULL, eventcb, NULL);
bufferevent_enable(bev, EV_READ);
}
int run_server()
{
int ret = 0;
struct sockaddr_in sin;
// new an event base
EventBase *base = event_base_new();
assert(base);
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = 0;
sin.sin_port = htons(5566);
// evconnlistener
struct evconnlistener *listener =
evconnlistener_new_bind(base, acceptcb, base,
LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE | LEV_OPT_CLOSE_ON_EXEC,
-1, (struct sockaddr *)&sin, sizeof(sin));
assert(listener);
assert(evconnlistener_get_fd(listener) != EVUTIL_INVALID_SOCKET);
// start event loop
// return 0 if successful, -1 if an error occurred, or 1 if we exited because no events were pending or active.
ret = event_base_dispatch(base);
assert(ret >= 0);
// free the event base
event_base_free(base);
return 0;
}
int main()
{
setbuf(stdout, NULL);
run_server();
return 0;
}
编译运行
g++ -o server sever.cpp -levent
./server
可以根据需要扩展适当的event事件、处理对应的信号。
如有其它疑问,请联系博主一起讨论学习。