做者:阿凡盧html
出處:http://www.cnblogs.com/luxiaoxun/windows
本文版權歸做者和博客園共有,歡迎轉載,但未經做者贊成必須保留此段聲明,且在文章頁面明顯位置給出原文鏈接,不然保留追究法律責任的權利。安全
vs命令行工具使用:http://tieba.baidu.com/p/3335013298網絡
Libevent官網:http://libevent.org/app
libevent API:http://www.monkey.org/~provos/libevent/doxygen-2.0.1/index.htmlsocket
比較不錯的參考:http://download.csdn.net/detail/sparkliang/2001038ide
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.lib:All core event and buffer functionality. This library contains all the event_base, evbuffer, bufferevent, and utility functions.
libevent_extras.lib:This library defines protocol-specific functionality that you may or may not want for your application, including HTTP, DNS, and RPC.
libevent.lib:This 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 lib下載 Libevent2.0.21.rar
初次使用vs2013因爲安全機制引起error的解決方法:
一、將過去的工程用VS2010打開的時候。你有可能會遇到一大堆的警告:warning C4996。
好比:warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS.
緣由是Visual C++ 2005使用了更加安全的run-time library routines。
新的Security CRT functions(就是那些帶有「_s」後綴的函數):
http://msdn2.microsoft.com/en-us/library/wd3wzwts(VS.80).aspx
那麼如何搞定這些警告呢:
緣由解釋
這種微軟的警告,主要由於那些C庫的函數,不少函數內部是不進行參數檢測的(包括越界類的),微軟擔憂使用這些會形成內存異常,因此就改寫了一樣功能的函數,改寫了的函數進行了參數的檢測,使用這些新的函數會更安全和便捷。關於這些改寫的函數你不用專門去記憶,由於編譯器對於每一個函數在給出警告時,都會告訴你相應的安全函數,查看警告信息就能夠獲知,在使用時也再查看一下MSDN詳細瞭解。庫函數改寫例子:
mkdir改寫爲 _mkdir
fopen」改寫爲 fopen_s
stricmp改寫爲 stricmp_s
sprintf改寫爲sprintf_s
strcpy改寫爲strcpy_s
解決方案:
1> 根據下面的warning提示:參見「fopen」的聲明
消息:「This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_DEPRECATE. See online help for details.」
因此能夠將函數按warning提示的第二句,改成使用fopen_s函數便可:
例如:FILE *pFile=fopen("1.txt", "w");
改成:
FILE* pFile;
fopen_s(&pFile, "1.txt", "w");
2> 仍是根據warning提示的地三句話:use _CRT_SECURE_NO_DEPRECATE
項目|屬性|配置屬性|C/C++|命令行|附加選項,加入【/D "_CRT_SECURE_NO_DEPRECATE" 】(注:加入中括號中完整的內容)
3> 下降警告級別:項目|屬性|配置屬性|C/C++|常規,本身根據狀況下降警告級別(此法不推薦)
注意:高度重視警告:使用編譯器的最高警告級別。應該要求構建是乾淨利落的(沒有警告)。理解全部警告。經過 修改代碼而不是下降警告級別來排除警告。
方法一:手工將原來的舊函數替換成新的Security CRT functions。
方法二:屏蔽這個警告。
在預編譯頭文件stdafx.h裏(注意:必定要在沒有include任何頭文件以前)定義下面的宏:
#define _CRT_SECURE_NO_DEPRECATE
或者#param warning(disable:4996)
方法二沒有使用新的更安全的CRT函數,顯然不是一個值得推薦的方法,但是你又不想一個一個地改。
那麼還有一個更方便的方法:
在預編譯頭文件stdafx.h裏(一樣要在沒有include任何頭文件以前)定義下面的宏:
#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1
在連接的時候便會自動將舊函數替換成Security CRT functions。
注意:這個方法雖然使用了新的函數,可是不能消除警告你還得同時使用方法二。。。
補充缺失的event-config.h:(附件)