1.The libevent API provides a mechanism[机制] to execute a callback function when a specific event occurs on a file descriptor or after a timeout has been reached. Furthermore, libevent also support callbacks due to signals or regular timeouts.
//支持I/O 信号 定时器
2.libevent supports /dev/poll, kqueue(2), event ports, POSIX select(2), Windows select(), poll(2), and epoll(4).
3.Libevent can also be used for multi-threaded applications, either by isolating[孤立] each event_base so that only a single thread accesses it, or by locked access to a single shared event_base.
//默认单线程,也可以用于多线程(一个线程一个event_base,或者加锁)。
跨平台、异步事件驱动:ACE_Reactor好像也是事件驱动、Reactor模式
// echo server.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include
#include
void do_accept(evutil_socket_t listener, short event, void *arg);
void read_cb(struct bufferevent *bev, void *arg);
void error_cb(struct bufferevent *bev, short event, void *arg);
void write_cb(struct bufferevent *bev, void *arg);
int _tmain(int argc, _TCHAR* argv[])
{
int ret = 0;
#ifdef WIN32
WSADATA wsa_data;
WSAStartup(0x0201, &wsa_data);
#endif
evutil_socket_t lsocket;
lsocket = socket(AF_INET,SOCK_STREAM,0);
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_addr.S_un.S_addr = 0;
sin.sin_port = htons(8889);
if(bind(lsocket,(struct sockaddr*)&sin,sizeof(sin)) < 0)
{
perror("bind");
return -1;
}
if(listen(lsocket,10) < 0)
{
perror("listen");
return -1;
}
struct event_base *base = event_base_new();
struct event* listen_event;
listen_event = event_new(base,lsocket,EV_READ|EV_PERSIST,do_accept,(void*)base);
event_add(listen_event,NULL);
event_base_dispatch(base);
return 0;
}
void do_accept(evutil_socket_t tsocket,short event,void *arg)
{
typedef int socklen_t;
struct event_base *base = (struct event_base*)arg;
struct sockaddr_in sin;
socklen_t slen = sizeof(sin);
evutil_socket_t fd = accept(tsocket,(struct sockaddr*)&sin,&slen);
if(fd < 0)
{
perror("accept");
return;
}
struct bufferevent *bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);
bufferevent_setcb(bev, read_cb, NULL, error_cb, arg);
bufferevent_enable(bev, EV_READ|EV_WRITE|EV_PERSIST);
}
void read_cb(struct bufferevent *bev, void *arg)
{
#define MAX_LINE 256
char line[MAX_LINE+1];
evutil_socket_t fd = bufferevent_getfd(bev);
int n = 0;
while (n = bufferevent_read(bev, line, MAX_LINE), n > 0)
{
line[n] = '\0';
printf("fd=%u, read line: %s\n", fd, line);
bufferevent_write(bev, line, n);
}
}
void write_cb(struct bufferevent *bev, void *arg)
{
}
void error_cb(struct bufferevent *bev, short event, void *arg)
{
evutil_socket_t fd = bufferevent_getfd(bev);
printf("fd = %u, ", fd);
if (event & BEV_EVENT_TIMEOUT)
{
printf("Timed out\n"); //if bufferevent_set_timeouts() called
}
else if (event & BEV_EVENT_EOF)
{
printf("connection closed\n");
}
else if (event & BEV_EVENT_ERROR)
{
printf("some other error\n");
}
bufferevent_free(bev);