轉(zhuǎn)自:http://name5566.com/4220.html
?
參考文獻(xiàn)列表:
http://www.wangafu.net/~nickm/libevent-book/
此文編寫的時(shí)候,使用到的 Libevent 為 2.0.21
Libevent 提供了連接監(jiān)聽器 evconnlistener
創(chuàng)建 evconnlistener 實(shí)例
- // 連接監(jiān)聽器回調(diào)函數(shù)原型
- typedef void (* evconnlistener_cb )(
- struct evconnlistener * listener ,
- // 新的 socket
- evutil_socket_t sock ,
- // 新的 socket 對(duì)應(yīng)的地址
- struct sockaddr * addr ,
- int len ,
- // 用戶自定義數(shù)據(jù)
- void * ptr
- );
- ?
- // 創(chuàng)建一個(gè)新的連接監(jiān)聽器
- struct evconnlistener * evconnlistener_new (
- struct event_base * base ,
- // 一個(gè)新的連接到來(lái)時(shí)此回調(diào)被調(diào)用
- evconnlistener_cb cb ,
- // 用戶自定義數(shù)據(jù),會(huì)被傳遞給 cb 回調(diào)函數(shù)
- void * ptr ,
- // 連接監(jiān)聽器的選項(xiàng)(下面會(huì)詳細(xì)談到)
- unsigned flags ,
- // 為標(biāo)準(zhǔn)的 listen 函數(shù)的 backlog 參數(shù)
- // 如果為負(fù)數(shù),Libevent 將嘗試選擇一個(gè)合適的值
- int backlog ,
- // socket
- // Libevent 假定此 socket 已經(jīng)綁定
- evutil_socket_t fd
- );
- ?
- // 創(chuàng)建一個(gè)新的連接監(jiān)聽器
- // 大多數(shù)參數(shù)含義同于 evconnlistener_new
- struct evconnlistener * evconnlistener_new_bind (
- struct event_base * base ,
- evconnlistener_cb cb ,
- void * ptr ,
- unsigned flags ,
- int backlog ,
- // 指定需要綁定的 socket 地址
- const struct sockaddr * sa ,
- int socklen
- );
連接監(jiān)聽器的常用選項(xiàng)如下:
-
LEV_OPT_CLOSE_ON_FREE
當(dāng)關(guān)閉連接監(jiān)聽器其底層 socket 也被自動(dòng)釋放 -
LEV_OPT_REUSEABLE
設(shè)置 socket 綁定的地址可以重用 -
LEV_OPT_THREADSAFE
設(shè)置連接監(jiān)聽器為線程安全的
釋放連接監(jiān)聽器
- void evconnlistener_free ( struct evconnlistener * lev );
錯(cuò)誤檢測(cè)
如果連接監(jiān)聽器出錯(cuò),我們可以得到通知:
- // 連接監(jiān)聽器錯(cuò)誤回調(diào)函數(shù)原型
- typedef void (* evconnlistener_errorcb )( struct evconnlistener * lis , void * ptr );
- ?
- // 為連接監(jiān)聽器設(shè)置錯(cuò)誤回調(diào)函數(shù)
- void evconnlistener_set_error_cb ( struct evconnlistener * lev ,
- evconnlistener_errorcb errorcb );
一個(gè)詳細(xì)的范例(echo 服務(wù)器)
- #include <event2/listener.h>
- #include <event2/bufferevent.h>
- #include <event2/buffer.h>
- ?
- #include <arpa/inet.h>
- ?
- #include <string.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <errno.h>
- ?
- // 讀取回調(diào)函數(shù)
- static void
- echo_read_cb ( struct bufferevent * bev , void * ctx )
- {
- struct evbuffer * input = bufferevent_get_input ( bev );
- struct evbuffer * output = bufferevent_get_output ( bev );
- ?
- // 將輸入緩沖區(qū)的數(shù)據(jù)直接拷貝到輸出緩沖區(qū)
- evbuffer_add_buffer ( output , input );
- }
- ?
- // 事件回調(diào)函數(shù)
- static void
- echo_event_cb ( struct bufferevent * bev , short events , void * ctx )
- {
- if ( events & BEV_EVENT_ERROR )
- perror ( "Error from bufferevent" );
- if ( events & ( BEV_EVENT_EOF | BEV_EVENT_ERROR )) {
- bufferevent_free ( bev );
- }
- }
- ?
- // 連接監(jiān)聽器回調(diào)函數(shù)
- static void
- accept_conn_cb ( struct evconnlistener * listener ,
- evutil_socket_t fd , struct sockaddr * address , int socklen ,
- void * ctx )
- {
- // 為新的連接分配并設(shè)置 bufferevent
- struct event_base * base = evconnlistener_get_base ( listener );
- struct bufferevent * bev = bufferevent_socket_new (
- base , fd , BEV_OPT_CLOSE_ON_FREE );
- ?
- bufferevent_setcb ( bev , echo_read_cb , NULL , echo_event_cb , NULL );
- ?
- bufferevent_enable ( bev , EV_READ | EV_WRITE );
- }
- ?
- // 連接監(jiān)聽器錯(cuò)誤回調(diào)函數(shù)
- static void
- accept_error_cb ( struct evconnlistener * listener , void * ctx )
- {
- struct event_base * base = evconnlistener_get_base ( listener );
- // 獲取到錯(cuò)誤信息
- int err = EVUTIL_SOCKET_ERROR ();
- fprintf ( stderr , "Got an error %d (%s) on the listener. "
- "Shutting down.\n" , err , evutil_socket_error_to_string ( err ));
- ?
- // 退出事件循環(huán)
- event_base_loopexit ( base , NULL );
- }
- ?
- int
- main ( int argc , char ** argv )
- {
- struct event_base * base ;
- struct evconnlistener * listener ;
- struct sockaddr_in sin ;
- ?
- int port = 9876 ;
- ?
- if ( argc > 1 ) {
- port = atoi ( argv [ 1 ]);
- }
- if ( port <= 0 || port > 65535 ) {
- puts ( "Invalid port" );
- return 1 ;
- }
- ?
- base = event_base_new ();
- if (! base ) {
- puts ( "Couldn't open event base" );
- return 1 ;
- }
- ?
- memset (& sin , 0 , sizeof ( sin ));
- sin . sin_family = AF_INET ;
- sin . sin_addr . s_addr = htonl ( 0 );
- sin . sin_port = htons ( port );
- ?
- listener = evconnlistener_new_bind ( base , accept_conn_cb , NULL ,
- LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE , - 1 ,
- ( struct sockaddr *) & sin , sizeof ( sin ));
- if (! listener ) {
- perror ( "Couldn't create listener" );
- return 1 ;
- }
- evconnlistener_set_error_cb ( listener , accept_error_cb );
- ?
- event_base_dispatch ( base );
- return 0 ;
- }
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
