您的位置:首页 > 其它

libevent相关基础

2016-12-24 15:15 363 查看
libevent是一个老牌的服务器底层引擎。质量还是非常好的。基本上很多不想编写服务器底层的团队都会选用这个底层。毕竟写一套出来,代码还是那些东西。

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创建好完成端口数据结构,信号量,创建工作线程。

更多的细节还需要多阅读它的源码。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  windows 服务器