一 主循环
每个服务器都有一个主循环,在开始主循环的过程中,会用到以下几个函数:
// 创建成功返回一个拥有默认设置的 event base // 创建失败返回 NULL struct event_base *event_base_new(void); // event_base 的释放 void event_base_free(struct event_base *base); // 指定一个 event_base 并开始事件循环 // 此函数内部被实现为一个不断进行的循环 // 此函数返回 0 表示成功退出 // 此函数返回 -1 表示存在未处理的错误 int event_base_dispatch(struct event_base *base);
代码示例如下:
int main() { // 创建默认设置的event base,失败返回NULL struct event_base* base = event_base_new(); // 开启时间循环 event_base_dispatch(base); // 释放 event_base_free(base); return 0; }
二 注册事件
libevent是事件驱动的,现在需要注册事件到主循环。
1 事件类型
// 超时 #define EV_TIMEOUT 0x01 // event 相关的文件描述符可以读了 #define EV_READ 0x02 // event 相关的文件描述符可以写了 #define EV_WRITE 0x04 // 被用于信号检测 #define EV_SIGNAL 0x08 // 用于指定 event 为 persistent #define EV_PERSIST 0x10 // 用于指定 event 会被边缘触发(Edge-triggered 可参考 http://name5566.com/3818.html) #define EV_ET
2 回调函数类型
// event 的回调函数 // 参数 evutil_socket_t --- event 关联的文件描述符 // 参数 short --- 当前发生的条件(也就是上面定义的条件) // 参数 void* --- 其为 event_new 函数中的 arg 参数 typedef void (*event_callback_fn)(evutil_socket_t, short, void *);
3 事件相关操作
// 创建 event // base --- 使用此 event 的 event_base // what --- 指定 event 关心的各种条件(也就是上面定义的条件) // fd --- 文件描述符 // cb --- event 相关的回调函数 // arg --- 用户自定义数据 // 函数执行失败返回 NULL struct event *event_new(struct event_base *base, evutil_socket_t fd, short what, event_callback_fn cb, void *arg); // 释放 event(真正释放内存,对应 event_new 使用) // 可以用来释放由 event_new 分配的 event // 若 event 处于 pending 或者 active 状态释放也不会存在问题 void event_free(struct event *event); // 清理 event(并不是真正释放内存) // 可用于已经初始化的、pending、active 的 event // 此函数会将 event 转换为非 pending、非 active 状态的 // 函数返回 0 表示成功 -1 表示失败 int event_del(struct event *event);
4 事件注册
// 用于向 event_base 中注册 event // tv 用于指定超时时间,为 NULL 表示无超时时间 // 函数返回 0 表示成功 -1 表示失败 int event_add(struct event *ev, const struct timeval *tv);
代码示例如下:
// 事件回调函数 void callBack(evutil_socket_t fd, short ev, void *args) { printf("%s\n", (char*)args); } int main() { // 创建默认设置的event base,失败返回NULL struct event_base* base = event_base_new(); // 创建事件 struct event* ev = event_new(base, NULL, EV_TIMEOUT, callBack, (char*)"TimeOut"); // 注册事件 const struct timeval outtime = {5, 0}; event_add(ev, &outtime); // 开启时间循环 event_base_dispatch(base); // 释放 event_base_free(base); return 0; }
三 其他配置和优化
在win32下需要初始化网络, 代码示例如下:
// 事件回调函数 void callBack(evutil_socket_t fd, short ev, void *args) { printf("%s\n", (char*)args); } int main() { // 初始化网络 WORD wVersionRequested = MAKEWORD(2, 2); WSADATA wsaData; WSAStartup(wVersionRequested, &wsaData); // 创建默认设置的event base,失败返回NULL struct event_base* base = event_base_new(); // 创建事件 struct event* ev = event_new(base, NULL, EV_TIMEOUT, callBack, (char*)"TimeOut"); // 注册事件 const struct timeval outtime = {5, 0}; event_add(ev, &outtime); // 开启时间循环 event_base_dispatch(base); // 释放 event_base_free(base); return 0; }
优化一下代码结构,最终代码如下:
#include <stdlib.h> #include <stdio.h> #include <Winsock2.h> #include <event2/event.h> #include <event2/util.h> // 初始化网络 void initNetwork() { WORD wVersionRequested = MAKEWORD(2, 2); WSADATA wsaData; (void)WSAStartup(wVersionRequested, &wsaData); } // 事件回调函数 void callBack(evutil_socket_t fd, short ev, void *args) { printf("%s\n", (char*)args); } // 开始主循环 void startEventLoop() { // 创建默认设置的event base,失败返回NULL struct event_base* base = event_base_new(); // 创建事件 struct event* ev = event_new(base, NULL, EV_TIMEOUT, callBack, (char*)"TimeOut"); // 注册事件 const struct timeval outtime = {5, 0}; event_add(ev, &outtime); // 开启时间循环 event_base_dispatch(base); // 释放 event_base_free(base); } int main() { initNetwork(); startEventLoop(); return 0; }
时间: 2024-10-08 03:08:32