libevent相关基础
2016-12-24 15:15
363 查看
libevent是一个老牌的服务器底层引擎。质量还是非常好的。基本上很多不想编写服务器底层的团队都会选用这个底层。毕竟写一套出来,代码还是那些东西。
修改“event_iocp.c”、“evthread_win32.c”、“listener.c”三个文件,在文件开头重新定义系统版本号:
默认定义为
备注系统对应关系:
在使用过程中如果你想去调试他的时候可以通过里面自带的调试日志接口,将他的日志接管,然后输出出来:
编译方式
回调函数:
其实这个也依赖于在创建event_base这个数据结构的时候自己要创建一个cfg的数据结构。将其中n_cpus(当前机器的cpu个数)设置好,cfg->flags 设置上 EVENT_BASE_FLAG_STARTUP_IOCP标记。
event_iocp.c文件中:
在这段代码里面将会为event_base创建好完成端口数据结构,信号量,创建工作线程。
更多的细节还需要多阅读它的源码。
windows debug开启
打开libevent的目录,找到Makefile.nmake文件。这个文件是用于做windows下nmake工具的makefile文件。CFLAGS=$(CFLAGS) /DUSE_DEBUG /Zi /Ox /W3 /wd4996 /nologo
修改“event_iocp.c”、“evthread_win32.c”、“listener.c”三个文件,在文件开头重新定义系统版本号:
#define _WIN32_WINNT 0x0500
默认定义为
#define _WIN32_WINNT 0x0403
备注系统对应关系:
Windows XP _WIN32_WINNT>=0x0501 Windows 2000 _WIN32_WINNT>=0x0500 Windows NT 4.0 _WIN32_WINNT>=0x0400 Windows Me _WIN32_WINDOWS=0x0490 Windows 98 _WIN32_WINDOWS>=0x0410
// // _WIN32_WINNT version constants // #define _WIN32_WINNT_NT4 0x0400 // Windows NT 4.0 #define _WIN32_WINNT_WIN2K 0x0500 // Windows 2000 #define _WIN32_WINNT_WINXP 0x0501 // Windows XP #define _WIN32_WINNT_WS03 0x0502 // Windows Server 2003 #define _WIN32_WINNT_WIN6 0x0600 // Windows Vista #define _WIN32_WINNT_VISTA 0x0600 // Windows Vista #define _WIN32_WINNT_WS08 0x0600 // Windows Server 2008 #define _WIN32_WINNT_LONGHORN 0x0600 // Windows Vista #define _WIN32_WINNT_WIN7 0x0601 // Windows 7 #define _WIN32_WINNT_WIN8 0x0602 // Windows 8 #define _WIN32_WINNT_WINBLUE 0x0603 // Windows 8.1 #define _WIN32_WINNT_WINTHRESHOLD 0x0A00 // Windows 10 #define _WIN32_WINNT_WIN10 0x0A00 // Windows 10
在使用过程中如果你想去调试他的时候可以通过里面自带的调试日志接口,将他的日志接管,然后输出出来:
void libevent_log_callback(int severity, const char *msg) { printf("[libEvent] debug Level: %d, msg: %s\n", severity, msg); } event_set_log_callback(libevent_log_callback);
编译方式
nmake /f Makefile.nmake
使用libevent连接
这里是参考libevent中的test中的openssl的源码。struct bufferevent *bev_; evutil_socket_t fd_; struct sockaddr_in in; if ((fd_ = socket(AF_INET, SOCK_STREAM, 0)) < 0) { printf("[NET] create socket fail"); return -1; } memset(&in,0, sizeof(struct sockaddr_in)); in.sin_family = AF_INET; in.sin_addr.s_addr = inet_addr(_remote_ip); in.sin_port = htons(_remote_port); bev_ = bufferevent_socket_new(base_ , fd_, BEV_OPT_CLOSE_ON_FREE); if (bev_ == NULL) { printf( "[NET] bufferevent_socket_new fail."); return -1; } bufferevent_setcb(bev_, &on_session_read, NULL , &on_session_event, NULL); if (bufferevent_socket_connect(session->bev_, (struct sockaddr *)&in, sizeof(in)) != 0) { print("[NET] failed."); return -1; }
回调函数:
void on_session_event(struct bufferevent *bev, short error, void *ctx) { if (error & BEV_EVENT_CONNECTED) { // 异步连接socket已经成功了 return; } ... }
使用iocp
可以阅读event.c文件中的struct event_base * event_base_new_with_config(const struct event_config *cfg) { ... #ifdef WIN32 if (cfg && (cfg->flags & EVENT_BASE_FLAG_STARTUP_IOCP)) event_base_start_iocp(base, cfg->n_cpus_hint); #endif int event_base_start_iocp(struct event_base *base, int n_cpus) { #ifdef WIN32 if (base->iocp) return 0; base->iocp = event_iocp_port_launch(n_cpus); if (!base->iocp) { event_warnx("%s: Couldn't launch IOCP", __func__); return -1; } return 0; #else return -1; #endif }
其实这个也依赖于在创建event_base这个数据结构的时候自己要创建一个cfg的数据结构。将其中n_cpus(当前机器的cpu个数)设置好,cfg->flags 设置上 EVENT_BASE_FLAG_STARTUP_IOCP标记。
event_iocp.c文件中:
#define N_CPUS_DEFAULT 2 struct event_iocp_port * event_iocp_port_launch(int n_cpus) { struct event_iocp_port *port; int i; if (!extension_fns_initialized) init_extension_functions(&the_extension_fns); if (!(port = mm_calloc(1, sizeof(struct event_iocp_port)))) return NULL; if (n_cpus <= 0) n_cpus = N_CPUS_DEFAULT; port->n_threads = n_cpus * 2; port->threads = mm_calloc(port->n_threads, sizeof(HANDLE)); if (!port->threads) goto err; port->port = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, n_cpus); port->ms = -1; if (!port->port) goto err; port->shutdownSemaphore = CreateSemaphore(NULL, 0, 1, NULL); if (!port->shutdownSemaphore) goto err; for (i=0; i<port->n_threads; ++i) { ev_uintptr_t th = _beginthread(loop, 0, port); if (th == (ev_uintptr_t)-1) goto err; port->threads[i] = (HANDLE)th; ++port->n_live_threads; } InitializeCriticalSectionAndSpinCount(&port->lock, 1000); return port; err: if (port->port) CloseHandle(port->port); if (port->threads) mm_free(port->threads); if (port->shutdownSemaphore) CloseHandle(port->shutdownSemaphore); mm_free(port); return NULL; }
在这段代码里面将会为event_base创建好完成端口数据结构,信号量,创建工作线程。
更多的细节还需要多阅读它的源码。
相关文章推荐
- 小心服务器内存居高不下的元凶--WebAPI服务
- 推送技术原理:移动无线网络长连接
- 运维入门
- 如何重装TCP/IP协议
- Windows 8 官方高清壁纸欣赏与下载
- 谁是桌面王者?Win PK Linux三大镇山之宝
- 对《大家都在点赞 Windows Terminal,我决定给你泼一盆冷水》一文的商榷
- Windows Clang开发环境备忘
- 从Windows系统下访问Linux分区相关软件
- 对《大家都在点赞 Windows Terminal,我决定给你泼一盆冷水》一文的商榷
- Windows下搭建本地SVN服务器
- 使用Windows原生命令一键清空剪贴板
- windows用windeployqt发布qt quick application程序
- 利用开源软件打造自己的全功能远程工具
- Linux5.9无人值守安装
- 数据中心和云未来的十二大趋势