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 }