[原]網絡庫libevent在Visual Studio中的使用方法

  libevent是一個事件觸發的網絡庫,適用於windows、linux、bsd等多種平臺,內部使用select、epoll、kqueue等系統調用管理事件機制。著名分佈式緩存軟件memcached也是libevent based,並且libevent在使用上能夠作到跨平臺,並且根據libevent官方網站上公佈的數據統計,彷佛也有着非凡的性能。php

一、下載編譯libeventlinux

  下載當前最新的libevent穩定版本libevent-2.0.21-stable.tar.gz安裝包,解壓到某個固定目錄。打開Visual Studio的Command Prompt終端,進入libevent-2.0.21-stable目錄,輸入以下指令編譯libevent代碼庫:windows

nmake /f Makefile.nmake

二、收集libevent相關頭文件和庫文件緩存

  libevent編譯完成後,生成的相關靜態庫文件包括三個:libevent.lib libevent_core.lib libevent_extras.lib,能夠單獨創建一個lib文件夾存放;網絡

  相關的頭文件包括三個地方:(1)libevent-2.0.12-stable\include\*   (2)libevent-2.0.12-stable\WIN32-Code\*    (3)libevent-2.0.12-stable\*.h多線程

把這些頭文件都複製一下放到一個單獨的include文件夾中方便管理。分佈式

三、在VS工程中指定libevent的include和lib文件夾ide

  有兩個地方指定:(1)新建一個工程後,在工程的「配置屬性」-->「C/C++」-->「常規」-->「附加包含目錄」中給出include文件夾路徑;(2)直接在VS「工具」-->「選項」-->「項目和解決方案」-->「VC++目錄」中給出include和lib目錄路徑。memcached

  相比而言,第一種方式我發如今代碼中雖然編譯不會出錯,可是不能自動定位頭文件和函數位置;第二種方式就可以清晰定位出libevent頭文件和函數的位置。函數

四、設置工程「運行時庫」屬性

  在工程的「配置屬性」-->「C/C++」-->「代碼生成」-->「運行時庫」中選擇「多線程(/MT)」(這裏須要與Libevent庫選擇相同的編譯版本,若是Libevent是Debug版本靜態庫,則可選擇/MD)

五、設置工程依賴和忽略函數庫

  在工程的「配置屬性」-->「連接器」-->「輸入」中指出「附加依賴項」包括:ws2_32.lib wsock32.lib libevent.lib libevent_core.lib libevent_extras.lib

  這一步的必要性在於,要使用libevent庫中的函數,必需要把函數的定義庫連接進來。其實,在代碼中讓編譯器鏈接也是同樣的,等價於在代碼中添加以下語句:

#include <WinSock2.h>
#include "event.h"

#pragma comment(lib, "ws2_32.lib")
#pragma comment(lib, "libevent.lib")
#pragma comment(lib, "libevent_core.lib")
#pragma comment(lib, "libevent_extras.lib")

六、測試代碼

  來一段測試代碼試一下:

 1 #include <stdio.h>
 2 #define WIN32_LEAN_AND_MEAN
 3 #include <windows.h>
 4 #include <winsock2.h>
 5 #include <event2/event.h>
 6 #include <event2/bufferevent.h>
 7 #include <event2/buffer.h>
 8 #include <evhttp.h>
 9 void root_handler(struct evhttp_request *req, void *arg)
10 {
11     struct evbuffer *buf = evbuffer_new();
12     if(!buf)
13     {
14         puts("failed to create response buffer");
15         return;
16     }
17     evbuffer_add_printf(buf, "Hello: %s\n", evhttp_request_uri(req));
18     evhttp_send_reply(req, HTTP_OK, "OK", buf);
19 }        
20 
21 void generic_handler(struct evhttp_request *req, void *arg)
22 {
23     struct evbuffer *buf = evbuffer_new();
24     if(!buf)
25     {
26         puts("failed to create response buffer");
27         return;
28     }
29     evbuffer_add_printf(buf, "Requested: %s\n", evhttp_request_uri(req));
30     evhttp_send_reply(req, HTTP_OK, "OK", buf);
31 }
32 
33 int main(int argc, wchar_t* argv[])
34 {
35     struct evhttp *httpd;    
36     WSADATA wsaData;
37     DWORD Ret;
38     if ((Ret = WSAStartup(MAKEWORD(2, 2), &wsaData)) != 0)
39     {
40         printf("WSAStartup failed with error %d\n", Ret);
41         return -1;
42     }
43     event_init();
44     httpd = evhttp_start("0.0.0.0", 8505);
45     if(!httpd)
46     {
47         return 1;
48     }
49     evhttp_set_cb(httpd, "/", root_handler, NULL);
50     evhttp_set_gencb(httpd, generic_handler, NULL);
51     printf("httpd server start OK!\n");
52     event_dispatch();
53     evhttp_free(httpd);
54     WSACleanup();
55     return 0;
56 }
View Code
相關文章
相關標籤/搜索