最近想要自己写一个简单的http server
,因为之前的那个是epoll
的,只能运行在linux
平台上。
于是我便找到了平台通用的libevent
。
libevent
是事件驱动的,支持异步的网络框架。
十分值得学习。
由于基于reactor
模型,所以事件抽象为event
,event loop
是reactor
,event handler
是各种回调函数。
struct event
要创建event
一般使用event_new
函数。
1 2
| struct event *event_new(struct event_base *base, evutil_socket_t fd, short what, event_callback_fn cb, void *arg);
|
base
参数是我们要把这个事件绑定的event loop
,
fd
就是socket fd
,只不过为了统一windows,重新定义了一下
what
是触发事件,
选项是下面的或
1 2 3 4 5 6
| #define EV_TIMEOUT 0x01 #define EV_READ 0x02 #define EV_WRITE 0x04 #define EV_SIGNAL 0x08 #define EV_PERSIST 0x10 #define EV_ET 0x20
|
cb
就是触发事件的回调函数,
arg
是我们自定义传进去的参数。
而回调函数的格式是一样的。 比如。
1
| void on_write(int conn_fd, short event, void *arg)
|
第一个conn_fd
就是我们event_new
中的fd
, 第二个便是what
,第三个是arg
。
struct event_base
创建event_base
使用。
1
| struct event_base* event_base_new()
|
把一个event
注册到event_base
中
1 2 3 4
| struct event *base = event_base_new(); struct event* ev_listen = event_new(base, listen_fd, EV_READ | EV_PERSIST, on_accept, NULL); event_base_set(base, ev_listen); event_add(ev_listen, NULL);
|
开始执行loop
1
| int event_base_dispatch(struct event_base *base);
|
还有类似free
函数
1 2
| event_base_free(struct event base*); event_free(struct event*);
|
一个简答的example
打开一个socket,每有一次连接进来便接受并关闭。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| int socket_bind_listen(char *addr, char *port) { int listen_fd; unsigned short Port; struct sockaddr_in addr_s; listen_fd = socket(AF_INET, SOCK_STREAM, 0); if (listen_fd == -1) { log_err("%s", strerror(errno)); exit(1); } Port = (unsigned short) atoi(port); memset(&addr_s, 0, sizeof(addr_s)); addr_s.sin_family = AF_INET; addr_s.sin_addr.s_addr = inet_addr(addr); addr_s.sin_port = htons(Port); int ret = bind(listen_fd, (struct sockaddr *) &addr_s, sizeof(addr_s)); if (ret == -1) { perror("bind:"); close(listen_fd); exit(1); } if (listen(listen_fd, BACKLOG) == -1) { perror("listen:") close(listen_fd); exit(1); } return listen_fd; } void on_accept(int listen_fd, short events, void *arg) { int conn_fd = accept(listen_fd, NULL, 0);
if (conn_fd < 0) { return; } printf("get connect\n"); close(conn_fd); } int main(int argc, char *argv[]) { int listen_fd = socket_bind_listen("127.0.0.1", "8080"); struct event_base *base = event_base_new(); struct event* ev_listen = event_new(base, listen_fd, EV_READ | EV_PERSIST, on_accept, NULL); event_base_set(base, ev_listen); event_add(ev_listen, NULL); event_base_dispatch(base); event_base_free(base); event_free(ev_listen); }
|