windows下编译及使用libevent

Libevent官网:http://libevent.org/

windows 7下编译:

编译环境 windows 7 + VS2010

(1)解压libevent到F:\libevent\libevent-2.0.21-stable

(2)打开Microsoft visual studio 2010命令行工具

(3)修改以下三个文件,添加宏定义:

在以下3个文件开头添加“#define _WIN32_WINNT 0x0500

libevent-2.0.21-stable\event_iocp.c

libevent-2.0.21-stable\evthread_win32.c

libevent-2.0.21-stable\listener.c

(4)使用VS命令提示工具编译:

cd/d F:\libevent\libevent-2.0.21-stable

nmake /f Makefile.nmake

(5)编译结果:

libevent_core.libAll core event and buffer functionality. This library contains all the event_base, evbuffer, bufferevent, and utility functions.

libevent_extras.libThis library defines protocol-specific functionality that you may or may not want for your application, including HTTP, DNS, and RPC.

libevent.libThis library exists for historical reasons; it contains the contents of both libevent_core and libevent_extra. You shouldn’t use it; it may go away in a future version of Libevent.

(6)VS2010下使用lib

新建一个VC++控制台项目:

环境配置:

项目下建一个Lib目录,将上面三个lib文件copy到该目录下。

新建一个Include目录,将F:\libevent\libevent-2.0.21-stable\include下的文件和文件夹copy到该目录下,F:\libevent\libevent-2.0.21-stable\WIN32-Code下的文件copy到该目录下,2个event2目录下的文件可合并一起。

main代码:

复制代码
// LibeventTest.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"

#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <signal.h>

#ifndef WIN32
#include <netinet/in.h>
# ifdef _XOPEN_SOURCE_EXTENDED
#  include <arpa/inet.h>
# endif
#include <sys/socket.h>
#endif

#include "event2/bufferevent.h"
#include "event2/buffer.h"
#include "event2/listener.h"
#include "event2/util.h"
#include "event2/event.h"

#include <WinSock2.h>

static const char MESSAGE[] = "Hello, World!\n";

static const int PORT = 9995;


static void conn_writecb(struct bufferevent *bev, void *user_data)
{
    struct evbuffer *output = bufferevent_get_output(bev);
    if (evbuffer_get_length(output) == 0) 
    {
        printf("flushed answer\n");
        bufferevent_free(bev);
    }
}

static void conn_eventcb(struct bufferevent *bev, short events, void *user_data)
{
    if (events & BEV_EVENT_EOF) 
    {
        printf("Connection closed.\n");
    } 
    else if (events & BEV_EVENT_ERROR) 
    {
        printf("Got an error on the connection: %s\n",
            strerror(errno));/*XXX win32*/
    }
    /* None of the other events can happen here, since we haven't enabled
     * timeouts */
    bufferevent_free(bev);
}

static void signal_cb(evutil_socket_t sig, short events, void *user_data)
{
    struct event_base *base = (struct event_base *)user_data;
    struct timeval delay = { 2, 0 };

    printf("Caught an interrupt signal; exiting cleanly in two seconds.\n");

    event_base_loopexit(base, &delay);
}

static void listener_cb(struct evconnlistener *listener, evutil_socket_t fd,
    struct sockaddr *sa, int socklen, void *user_data)
{
    struct event_base *base = (struct event_base *)user_data;
    struct bufferevent *bev;

    bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);
    if (!bev) 
    {
        fprintf(stderr, "Error constructing bufferevent!");
        event_base_loopbreak(base);
        return;
    }
    bufferevent_setcb(bev, NULL, conn_writecb, conn_eventcb, NULL);
    bufferevent_enable(bev, EV_WRITE);
    bufferevent_disable(bev, EV_READ);

    bufferevent_write(bev, MESSAGE, strlen(MESSAGE));
}

int main(int argc, char **argv)
{
    struct event_base *base;
    struct evconnlistener *listener;
    struct event *signal_event;

    struct sockaddr_in sin;

#ifdef WIN32
    WSADATA wsa_data;
    WSAStartup(0x0201, &wsa_data);
#endif

    base = event_base_new();
    if (!base) 
    {
        fprintf(stderr, "Could not initialize libevent!\n");
        return 1;
    }

    memset(&sin, 0, sizeof(sin));
    sin.sin_family = AF_INET;
    sin.sin_port = htons(PORT);

    listener = evconnlistener_new_bind(base, listener_cb, (void *)base,
        LEV_OPT_REUSEABLE|LEV_OPT_CLOSE_ON_FREE, -1,
        (struct sockaddr*)&sin,
        sizeof(sin));

    if (!listener) 
    {
        fprintf(stderr, "Could not create a listener!\n");
        return 1;
    }

    signal_event = evsignal_new(base, SIGINT, signal_cb, (void *)base);

    if (!signal_event || event_add(signal_event, NULL)<0) 
    {
        fprintf(stderr, "Could not create/add a signal event!\n");
        return 1;
    }

    event_base_dispatch(base);

    evconnlistener_free(listener);
    event_free(signal_event);
    event_base_free(base);

    printf("done\n");
    return 0;
}
复制代码

项目属性设置:

VC++目录:

包含目录,添加:F:\Projects\LibeventTest\LibeventTest\Include;

库目录,添加:F:\Projects\LibeventTest\LibeventTest\Lib;

C/C++:

代码生成-->运行库:多线程调试 (/MTd)(Debug下),多线程 (/MT)(Release下)

连接器:

输入:ws2_32.lib;wsock32.lib;libevent.lib;libevent_core.lib;libevent_extras.lib;

ws2_32.lib;wsock32.lib;是用来编译Windows网络相关的程序库。

编译,生成!


libevent在windows下使用步骤详解

libevent是一个常用的网络库,下面就看看在windows下面编译测试的过程吧。

一 环境

系统:win8.1
编译器:VS2013
官方下载地址:http://libevent.org/
版本:2.0.22-stable

二 编译静态库

1 解压
把上面下载到libevent-2.0.22-stable.tar.gz解压,得到libevent-2.0.22-stable文件夹


2 添加宏定义
在libevent-2.0.22-stable文件夹下找到下面三个文件:
event_iocp.c
evthread_win32.c
listener.c
打开并在开头加上宏定义:
#define _WIN32_WINNT 0x0500

因为event_iocp.c里用到<winbase.h>头文件里的函数定义,如InitializeCriticalSectionAndSpinCount,
<windows.h>会包含<winbase.h>,而<winbase.h>这个头文件里这个函数是这样定义的:
#if (_WIN32_WINNT >= 0x0403)
 WINBASEAPI
 BOOL WINAPI
 InitializeCriticalSectionAndSpinCount(
     __out LPCRITICAL_SECTION lpCriticalSection,
     __in  DWORD dwSpinCount
     );

 WINBASEAPI
 DWORD
 WINAPI
 SetCriticalSectionSpinCount(
     __inout LPCRITICAL_SECTION lpCriticalSection,
     __in    DWORD dwSpinCount
     );
 #endif

所以要定义_WIN32_WINNT这个宏,而且值要大于0x0403。
如果没有这个宏或不满足条件,编译器会假定这个函数没有定义,
等到链接时再寻找它,这样这个函数的符号就假定返回一个int,
而显示标准库文件里这个函数不是返回int,所以在链接时就会找不到这个函数符号。


注意:宏一定要定义在#include <windows.h>之前,不然还是没有作用。


3 编译
使用vs的命令行工具,cd到libevent-2.0.22-stable目录,执行脚本makefile.nmake,命令如下:
nmake /f Makefile.nmake
这样就会生成三个静态库:
libevent_core.lib
libevent_extras.lib
libevent.lib

三 使用示例

1 新建项目

新建一个控制台“空”项目


2 拷贝文件

2.1 在项目目录下建一个libevent文件夹
2.2 在libevent中新建一个lib文件夹,将上面三个lib文件copy到该目录下。
2.3 在libevent中再新建一个include文件夹,
将libevent-2.0.22-stable\include下的文件和文件夹copy到该目录下,
将libevent-2.0.22-stable\WIN32-Code下的文件和文件夹copy到该目录下,
2个event2目录下的文件合并一起。

3 项目配置

VC++目录:
包含目录,添加刚刚新建的include目录
库目录,添加刚刚的lib目录;


C/C++:
代码生成-->运行库:
Debug模式下选:多线程调试 (/MTd),
Release下模式下选:多线程 (/MT)


连接器:
输入->附加依赖项:
ws2_32.lib
wsock32.lib
libevent.lib
libevent_core.lib
libevent_extras.lib
另外两个库ws2_32.lib和wsock32.lib是用来编译Windows网络相关的程序库。

4 测试代码

4.1 新建一个main.c文件
4.2 从libevent-2.0.22-stable\sample目录下拷贝time-test.c文件中的代码到main中,代码如下:
[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. #include <sys/types.h>  
  2.   
  3.   
  4. #include <event2/event-config.h>  
  5.   
  6.   
  7. #include <sys/stat.h>  
  8. #ifndef WIN32  
  9. #include <sys/queue.h>  
  10. #include <unistd.h>  
  11. #endif  
  12. #include <time.h>  
  13. #ifdef _EVENT_HAVE_SYS_TIME_H  
  14. #include <sys/time.h>  
  15. #endif  
  16. #include <fcntl.h>  
  17. #include <stdlib.h>  
  18. #include <stdio.h>  
  19. #include <string.h>  
  20. #include <errno.h>  
  21.   
  22.   
  23. #include <event2/event.h>  
  24. #include <event2/event_struct.h>  
  25. #include <event2/util.h>  
  26.   
  27.   
  28. #ifdef WIN32  
  29. #include <winsock2.h>  
  30. #endif  
  31.   
  32.   
  33.   
  34.   
  35. struct timeval lasttime;  
  36.   
  37.   
  38. int event_is_persistent;  
  39.   
  40.   
  41. static void timeout_cb(evutil_socket_t fd, short event, void *arg)  
  42. {  
  43.     struct timeval newtime, difference;  
  44.     struct event *timeout = arg;  
  45.     double elapsed;  
  46.   
  47.   
  48.     evutil_gettimeofday(&newtime, NULL);  
  49.     evutil_timersub(&newtime, &lasttime, &difference);  
  50.     elapsed = difference.tv_sec +  
  51.         (difference.tv_usec / 1.0e6);  
  52.   
  53.   
  54.     printf("timeout_cb called at %d: %.3f seconds elapsed.\n",  
  55.         (int)newtime.tv_sec, elapsed);  
  56.     lasttime = newtime;  
  57.   
  58.   
  59.     if (!event_is_persistent) {  
  60.         struct timeval tv;  
  61.         evutil_timerclear(&tv);  
  62.         tv.tv_sec = 2;  
  63.         event_add(timeout, &tv);  
  64.     }  
  65. }  
  66.   
  67.   
  68. int main(int argc, char **argv)  
  69. {  
  70.     struct event timeout;  
  71.     struct timeval tv;  
  72.     struct event_base *base;  
  73.     int flags;  
  74.   
  75.   
  76. #ifdef WIN32  
  77.     WORD wVersionRequested;  
  78.     WSADATA wsaData;  
  79.   
  80.   
  81.     wVersionRequested = MAKEWORD(2, 2);  
  82.   
  83.   
  84.     (void)WSAStartup(wVersionRequested, &wsaData);  
  85. #endif  
  86.   
  87.   
  88.     if (argc == 2 && !strcmp(argv[1], "-p")) {  
  89.         event_is_persistent = 1;  
  90.         flags = EV_PERSIST;  
  91.     }  
  92.     else {  
  93.         event_is_persistent = 0;  
  94.         flags = 0;  
  95.     }  
  96.   
  97.   
  98.     /* Initalize the event library */  
  99.     base = event_base_new();  
  100.   
  101.   
  102.     /* Initalize one event */  
  103.     event_assign(&timeout, base, -1, flags, timeout_cb, (void*)&timeout);  
  104.   
  105.   
  106.     evutil_timerclear(&tv);  
  107.     tv.tv_sec = 2;  
  108.     event_add(&timeout, &tv);  
  109.   
  110.   
  111.     evutil_gettimeofday(&lasttime, NULL);  
  112.   
  113.   
  114.     event_base_dispatch(base);  
  115.   
  116.   
  117.     return (0);  
  118. }  

4.3 编译运行结果如图: