生活随笔
收集整理的這篇文章主要介紹了
libevent简介和使用
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
libevent是一個基于事件觸發(fā)的網(wǎng)絡(luò)庫,memcached底層也是使用libevent庫,今天學(xué)習(xí)下。
總體來說,libevent有下面一些特點和優(yōu)勢:
* 統(tǒng)一數(shù)據(jù)源, 統(tǒng)一I/O事件,信號和定時器這三種事件;
* 可移植,跨平臺支持多種I/O多路復(fù)用技術(shù), epoll、poll、dev/poll、select 和kqueue 等;
* 對并發(fā)編程支持,避免競態(tài)條件;
* 高性能,由事件驅(qū)動;
* 輕量級,專注于網(wǎng)絡(luò);
libevent有下面幾大部分組成:
*?事件管理包括各種IO(socket)、定時器、信號等事件,也是libevent應(yīng)用最廣的模塊;
*?緩存管理是指evbuffer功能;
*?DNS是libevent提供的一個異步DNS查詢功能;
*?HTTP是libevent的一個輕量級http實現(xiàn),包括服務(wù)器和客戶端
一些資料:
* libevent官網(wǎng):http://libevent.org/?
* libevent API:http://www.monkey.org/~provos/libevent/doxygen-2.0.1/index.html
* CSDN上剖析得很贊的文章:http://blog.csdn.net/sparkliang/article/details/4957667
// =============================================================================================
下面寫了2個簡單的使用例子,一個是定時器,一個是TCP服務(wù)器,都只涉及到libevent的事件管理模塊。
一、簡單定時器:實現(xiàn)程序每秒輸出一個“Game Over!”
event_init() =>?evtimer_set() =>?event_add() =>event_dispatch()
[cpp]?view plaincopy
#include?<stdio.h>?? #include?<iostream>?? ?? ?? #include?<event.h>?? using?namespace?std;?? ?? ?? void?onTime(int?sock,?short?event,?void?*arg)?? {?? ????cout?<<?"Game?Over!"?<<?endl;?? ?? ????struct?timeval?tv;?? ????tv.tv_sec?=?1;?? ????tv.tv_usec?=?0;?? ?????? ????event_add((struct?event*)arg,?&tv);?? }?? ?? int?main()?? {?? ?????? ????event_init();?? ?? ????struct?event?evTime;?? ?????? ????evtimer_set(&evTime,?onTime,?&evTime);?? ?? ????struct?timeval?tv;?? ????tv.tv_sec?=?1;?? ????tv.tv_usec?=?0;?? ?????? ????event_add(&evTime,?&tv);?? ?? ?????? ????event_dispatch();?? ?? ????return?0;?? }??
編譯并執(zhí)行,編譯加 -levent:
[cpp]?view plaincopy
gapp_devnet_1:/data/home/andyawang/code/2013_11/LibeventTest?#?mv?time.cpp?timer.cpp?? gapp_devnet_1:/data/home/andyawang/code/2013_11/LibeventTest?#?g++?-o?timer?timer.cpp?-levent?? gapp_devnet_1:/data/home/andyawang/code/2013_11/LibeventTest?#?./timer??? Game?Over!?? Game?Over!?? Game?Over!?? Game?Over!??
二、TCP服務(wù)器:
實現(xiàn)監(jiān)聽本機8888端口并輸出客戶端發(fā)送過來的信息
event_base_new()=>event_set()=>event_base_set()=>event_add()=>event_base_dispatch()
[cpp]?view plaincopy
#include?<stdio.h>?? #include?<string.h>?? #include?<iostream>?? #include?<sys/socket.h>?????? #include?<netinet/in.h>?????? #include?<arpa/inet.h>?????? #include?<netdb.h>?? ?? #include?<event.h>?? using?namespace?std;?? ?? ?? struct?event_base*?base;?? ?? ?? void?onRead(int?iCliFd,?short?iEvent,?void?*arg)?? {?? ????int?iLen;?? ????char?buf[1500];?? ?? ????iLen?=?recv(iCliFd,?buf,?1500,?0);?? ?? ????if?(iLen?<=?0)?{?? ????????cout?<<?"Client?Close"?<<?endl;?? ?? ?????????? ????????struct?event?*pEvRead?=?(struct?event*)arg;?? ????????event_del(pEvRead);?? ????????delete?pEvRead;?? ?? ????????close(iCliFd);?? ????????return;?? ????}?? ?? ????buf[iLen]?=?0;?? ????cout?<<?"Client?Info:"?<<?buf?<<?endl;?? }?? ?? ?? void?onAccept(int?iSvrFd,?short?iEvent,?void?*arg)?? {?? ????int?iCliFd;?? ????struct?sockaddr_in?sCliAddr;?? ?? ????socklen_t?iSinSize?=?sizeof(sCliAddr);?? ????iCliFd?=?accept(iSvrFd,?(struct?sockaddr*)&sCliAddr,?&iSinSize);?? ?? ?????? ????struct?event?*pEvRead?=?new?event;?? ????event_set(pEvRead,?iCliFd,?EV_READ|EV_PERSIST,?onRead,?pEvRead);?? ????event_base_set(base,?pEvRead);?? ????event_add(pEvRead,?NULL);?? }?? ?? int?main()?? {?? ?? ????int?iSvrFd;???? ????struct?sockaddr_in?sSvrAddr;?? ???????????????? ????memset(&sSvrAddr,?0,?sizeof(sSvrAddr));???? ????sSvrAddr.sin_family?=?AF_INET;???? ????sSvrAddr.sin_addr.s_addr?=?inet_addr("127.0.0.1");?????? ????sSvrAddr.sin_port?=?htons(8888);????? ?????????????????????????????? ?????? ????iSvrFd?=?socket(AF_INET,?SOCK_STREAM,?0);???? ????bind(iSvrFd,?(struct?sockaddr*)&sSvrAddr,?sizeof(sSvrAddr));???? ????listen(iSvrFd,?10);?? ?? ?????? ????base?=?event_base_new();?? ?????? ????struct?event?evListen;?? ?????? ????event_set(&evListen,?iSvrFd,?EV_READ|EV_PERSIST,?onAccept,?NULL);?? ?????? ????event_base_set(base,?&evListen);?? ?????? ????event_add(&evListen,?NULL);?? ?????? ?????? ????event_base_dispatch(base);?? ?? ????return?0;?? } ?
三. HTTP服務(wù)器
? ?
C代碼??
#include?<stdio.h>?? #include?<stdlib.h>?? #include?<unistd.h>?? #include?<event.h>?? #include?<evhttp.h>?? ?? void?reqHandler(struct?evhttp_request?*req,void?*arg)?? {?? ????struct?evbuffer?*buf?=?evbuffer_new();?? ?????? ?????? ????evbuffer_add_printf(buf,?"Thanks?for?the?request");?? ????evhttp_send_reply(req,HTTP_OK,"Client",buf);?? ?????? ????evbuffer_free(buf);?? ?????? ????return;?? }?
void http_handle(struct evhttp_request* req, void* arg)
{
??? struct evbuffer* buffer = evbuffer_new();
??? // 獲取客戶端請求的URL
??? const char* url;
??? url = evhttp_request_uri(req);
??? evbuffer_add_printf(buffer, "url = %s\n", url);
??? // 解析url的參數(shù)(即GET方法的參數(shù))
??? struct evkeyvalq params;
??? evhttp_parse_query(url, ¶ms);
??? evbuffer_add_printf(buffer, "a = %s\n", evhttp_find_header(¶ms, "a"));
??? evbuffer_add_printf(buffer, "b = %s\n", evhttp_find_header(¶ms, "b"));
??? // 設(shè)置HTTP表頭
??? evhttp_add_header(req->output_headers, "Server", "mytest http server 0.1");
??? evhttp_add_header(req->output_headers, "Content-Type", "text/plain;charset=UTF-8");
??? evhttp_add_header(req->output_headers, "Connection", "close");
??? // 返回數(shù)據(jù)
??? evhttp_send_reply(req, HTTP_OK, "OK", buffer);
??? evbuffer_free(buffer);
}
int?main(int?argc,char?**argv)?? {?? ????short?port?=?8000;?? ????const?char?*addr?=?"192.168.1.11";?? ????struct?evhttp?*httpserv?=?NULL;?? ?? ????event_init();?? ?????????? ????httpserv?=?evhttp_start(addr,port);?? ?? ?????? ????evhttp_set_gencb(httpserv,?reqHandler,NULL);?? ????printf("Server?started?on?port?%d\n",port);?? ?? ????event_dispatch();?? ?? ????return?0;?? }??
? ? 瀏覽器訪問:?http://192.168.1.11:8000?會顯示 Thanks for the request
#include?<stdio.h>?? #include?<stdlib.h>?? #include?<unistd.h>?? #include?<event.h>?? #include?<evhttp.h>?? ?? void?reqHandler(struct?evhttp_request?*req,void?*arg)?? {?? ????struct?evbuffer?*buf?=?evbuffer_new();?? ?????? ?????? ????evbuffer_add_printf(buf,?"Thanks?for?the?request");?? ????evhttp_send_reply(req,HTTP_OK,"Client",buf);?? ?????? ????evbuffer_free(buf);?? ?????? ????return;?? }?
void http_handle(struct evhttp_request* req, void* arg)
{
??? struct evbuffer* buffer = evbuffer_new();
??? // 獲取客戶端請求的URL
??? const char* url;
??? url = evhttp_request_uri(req);
??? evbuffer_add_printf(buffer, "url = %s\n", url);
??? // 解析url的參數(shù)(即GET方法的參數(shù))
??? struct evkeyvalq params;
??? evhttp_parse_query(url, ¶ms);
??? evbuffer_add_printf(buffer, "a = %s\n", evhttp_find_header(¶ms, "a"));
??? evbuffer_add_printf(buffer, "b = %s\n", evhttp_find_header(¶ms, "b"));
??? // 設(shè)置HTTP表頭
??? evhttp_add_header(req->output_headers, "Server", "mytest http server 0.1");
??? evhttp_add_header(req->output_headers, "Content-Type", "text/plain;charset=UTF-8");
??? evhttp_add_header(req->output_headers, "Connection", "close");
??? // 返回數(shù)據(jù)
??? evhttp_send_reply(req, HTTP_OK, "OK", buffer);
??? evbuffer_free(buffer);
}
int?main(int?argc,char?**argv)?? {?? ????short?port?=?8000;?? ????const?char?*addr?=?"192.168.1.11";?? ????struct?evhttp?*httpserv?=?NULL;?? ?? ????event_init();?? ?????????? ????httpserv?=?evhttp_start(addr,port);?? ?? ?????? ????evhttp_set_gencb(httpserv,?reqHandler,NULL);?? ????printf("Server?started?on?port?%d\n",port);?? ?? ????event_dispatch();?? ?? ????return?0;?? }?
總結(jié)
以上是生活随笔為你收集整理的libevent简介和使用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。