libevent使用IOCP网络模型的示例
生活随笔
收集整理的這篇文章主要介紹了
libevent使用IOCP网络模型的示例
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
這段時間抽空學習了一下強大的網(wǎng)絡庫libevent,其使用標準C語言編寫,支持Windows、Linux、Mac等等主流操作系統(tǒng),早期版本不支持Windows的IOCP,最新版本已經(jīng)添加上了,在網(wǎng)上找了一下資料,發(fā)現(xiàn)使用IOCP的libevent示例太少,于是結(jié)合網(wǎng)上的資料,自己整理編寫了一下libevent使用IOCP的小例子。該示例同時支持IPV4以及IPV6的連接。
#ifdef __cplusplus extern "C" { #endif//包含所需要的頭文件 #include "event2/event.h" #include "event2/listener.h" #include "event2/bufferevent.h" #include "event2/thread.h" #include "event2/buffer.h"#ifdef __cplusplus }; #endif#ifdef _MSC_VER #pragma comment(lib,"ws2_32.lib") #pragma comment(lib,"libevent_core.lib") #endif//監(jiān)聽回調(diào)函數(shù) void listener_cb(evconnlistener *listener, evutil_socket_t fd,struct sockaddr *sock, int socklen, void *arg); //從Socket接收消息的回調(diào)函數(shù) void socket_read_cb(bufferevent *bev, void *arg);//從Socket事件的回調(diào)函數(shù) void socket_event_cb(bufferevent *bev, short events, void *arg); int main() { WORD wVersionRequested;WSADATA wsaData;int err;/* Use the MAKEWORD(lowbyte, highbyte) macro declared in Windef.h */wVersionRequested = MAKEWORD(2, 2);//這里必須初始化網(wǎng)絡,不然會創(chuàng)建Socket失敗err = WSAStartup(wVersionRequested, &wsaData);if (err != 0) {/* Tell the user that we could not find a usable *//* Winsock DLL. */printf("WSAStartup failed with error: %d\n", err);return 1;}struct sockaddr_in sin;memset(&sin, 0, sizeof(struct sockaddr_in));sin.sin_family = AF_INET;sin.sin_port = htons(2000);struct sockaddr_in6 sin6;memset(&sin6, 0, sizeof(struct sockaddr_in6));sin6.sin6_family = AF_INET6;sin6.sin6_port = htons(2000);//告訴libEvent使用Windows線程//這句是必須的,不然會導致event_base_dispatch時一直處于Sleep狀態(tài),無法正常工作evthread_use_windows_threads();struct event_config* cfg = event_config_new();event_config_set_flag(cfg,EVENT_BASE_FLAG_STARTUP_IOCP);//根據(jù)CPU實際數(shù)量配置libEvent的CPU數(shù)SYSTEM_INFO si;GetSystemInfo(&si);event_config_set_num_cpus_hint(cfg,si.dwNumberOfProcessors);event_base *base;base = event_base_new_with_config(cfg); event_config_free(cfg);// 綁定并監(jiān)聽IPV4端口evconnlistener *listener = evconnlistener_new_bind(base, listener_cb, base, LEV_OPT_REUSEABLE|LEV_OPT_CLOSE_ON_FREE, 10, (struct sockaddr*)&sin, sizeof(sin));// 綁定并監(jiān)聽IPV6端口evconnlistener *listener6 = evconnlistener_new_bind(base, listener_cb, base, LEV_OPT_REUSEABLE|LEV_OPT_CLOSE_ON_FREE, 10, (struct sockaddr*)&sin6, sizeof(sin6));//事件分發(fā)處理event_base_dispatch(base); evconnlistener_free(listener);evconnlistener_free(listener6);event_base_free(base);WSACleanup();return 0; }//一個新客戶端連接上服務器了 //當此函數(shù)被調(diào)用時,libevent已經(jīng)幫我們accept了這個客戶端。該客戶端的 //文件描述符為fd void listener_cb(evconnlistener *listener, evutil_socket_t fd, struct sockaddr *sock, int socklen, void *arg) { char Buffer[256];sockaddr_in* addr = (sockaddr_in*)sock;evutil_inet_ntop(addr->sin_family,&addr->sin_addr,Buffer,sizeof(Buffer));printf("accept a client %d,IP:%s\n", fd,Buffer);event_base *base = (event_base*)arg; //為這個客戶端分配一個bufferevent bufferevent *bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE | BEV_OPT_THREADSAFE); bufferevent_setcb(bev, socket_read_cb, NULL, socket_event_cb, NULL); bufferevent_enable(bev, EV_READ | EV_PERSIST); }void socket_read_cb(bufferevent *bev, void *arg) { char msg[4096];size_t len;// 這里一行一行的讀取char* p = evbuffer_readln(bufferevent_get_input(bev),&len,EVBUFFER_EOL_ANY);if(p){// 如果輸入exit或者quit則退出程序// 可以使用event_base_loopexit或者event_base_loopbreak// 它們的區(qū)別是前者會把事件處理完才退出,后者是立即退出if(!strcmp(p,"exit"))event_base_loopexit(bufferevent_get_base(bev),NULL);else if (!strcmp(p,"quit"))event_base_loopbreak(bufferevent_get_base(bev));printf("recv data:%s\n", p); int n = sprintf_s(msg,"srv recv data:%s\n",p);//發(fā)送消息給客戶端bufferevent_write(bev, msg, n );// 這里記得把分配的內(nèi)存釋放掉,不然會內(nèi)存泄漏free(p);} }void socket_event_cb(bufferevent *bev, short events, void *arg) { if (events & BEV_EVENT_EOF) printf("connection closed\n"); else if (events & BEV_EVENT_ERROR) printf("some other error\n"); //這將自動close套接字和free讀寫緩沖區(qū) bufferevent_free(bev); }?
?轉(zhuǎn)載于:https://www.cnblogs.com/witton/p/6868962.html
總結(jié)
以上是生活随笔為你收集整理的libevent使用IOCP网络模型的示例的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: js获取上传文件内容
- 下一篇: Redis AOF 全持久化