欧美三区_成人在线免费观看视频_欧美极品少妇xxxxⅹ免费视频_a级毛片免费播放_鲁一鲁中文字幕久久_亚洲一级特黄

Libevent(4)— Bufferevent

系統 2572 0

轉自:http://name5566.com/4215.html

?

參考文獻列表:
http://www.wangafu.net/~nickm/libevent-book/

此文編寫的時候,使用到的 Libevent 為 2.0.21

Buffer IO 模式

bufferevent 提供給我們一種 Buffer IO 模式(這里以寫入數據為例):

  1. 在我們需要通過某個連接發送數據的時候,先將等待發送的數據放入到一個 buffer 中
  2. 等待此連接可以寫入數據
  3. 盡可能多的獲取 buffer 中的數據寫入此連接
  4. 如果 buffer 中還有需要寫入的數據則繼續等待直到此連接可以寫入數據

每一個 bufferevent 都包含了一個輸入 buffer 和一個輸出 buffer,它們的類型為 evbuffer(結構體)。當我們向 bufferevent 寫入數據的時候,實際上數據首先被寫入到了輸出 buffer,當 bufferevent 有數據可讀時,我們實際上是從輸入 buffer 中獲取數據。

目前 bufferevent 目前僅僅支持 stream-oriented 的協議(例如 TCP)并不支持 datagram-oriented 協議(例如 UDP)。一個 bufferevent 的實例負責一個特定的連接上的數據收發。

Libevent 可以按需要創建多種類型的 bufferevent:

  1. 基于 socket 的 bufferevent。此類型的 bufferevent 使用 socket 來進行數據的收發,使用 event 機制來判斷 socket 是否可以進行讀寫操作
  2. 異步 IO bufferevent。此類型的 bufferevent 使用 IOCP 接口實現(僅 Windows 下可用且目前處于實驗階段)
  3. Filtering bufferevent。此類型的 bufferevent 可以在同底層交互時完成一些額外的數據處理工作,例如可以完成數據的壓縮和解析工作。這種類型的 bufferevent 的一個實例會封裝了另外的一個 bufferevent,我們把這個被封裝的 bufferevent 叫做底層 bufferevent
  4. Paired bufferevent。本文不談

bufferevent 的回調函數

每個 bufferevent 實例可以有 3 個回調函數(通過接口 bufferevent_setcb 設置):

  1. 讀取回調函數。默認情況下,只要從底層讀取到了數據此回調函數將被調用
  2. 寫入回調函數。默認情況下,足夠多的數據被寫入底層此回調函數將被調用
  3. 事件回調函數。當某些事件(錯誤)發生時被調用

對于 buffer 的讀、寫和回調行為可以通過幾個參數來配置,這幾個參數在 Libevent 中被叫做 watermark(水位標記,我們可以將 buffer 想象為一個水池,水位標記用于標記水池中水的多少,也就是說,watermark 用于標記 buffer 中的數據量)。watermark 被實現為整數(類型為 size_t),有幾種類型的 watermark:

  1. Read low-water mark 用于控制讀取回調函數的行為。當 bufferevent 進行讀取操作時,Read low-water mark 的值決定了輸入 buffer 有多少數據后調用讀取回調函數。默認的情況下,此值為 0,因此 bufferevent 讀取操作都會導致讀取回調函數被調用
  2. Read high-water mark 用于控制輸入 buffer 的大小。如果輸入 buffer 中的數據量達到 Read high-water mark 的值,那么 bufferevent 將停止讀取。默認的情況下,此值為無限大
  3. Write low-water mark,用于控制寫入回調函數的行為。當 bufferevent 進行寫入操作時,Write low-water mark 的值決定了輸出 buffer 有多少數據后調用寫入回調函數。默認的情況下,此值為 0,因此寫入回調函數會在輸出 buffer 為空的時候被調用
  4. Write high-water mark,此值在使用 Filtering bufferevent 有特殊的用途

在一些特殊需求中(詳細并不討論),我們可能需要回調函數被延時執行(這種被延時的回調函數被叫做 Deferred callbacks)。延時回調函數會在事件循環中排隊,并在普通事件回調函數(regular event’s callback)之后被調用。

從基于 socket 的 bufferevent 開始認識 bufferevent

創建基于 socket 的 bufferevent:

  1. // 創建一個基于 socket 的 bufferevent
  2. // 函數執行失敗返回 NULL
  3. struct bufferevent * bufferevent_socket_new (
  4. struct event_base * base ,
  5. // socket 文件描述符
  6. // 此 socket 必須被設置為非阻塞的
  7. // 可以設置為 -1 表示之后再設置
  8. evutil_socket_t fd ,
  9. // bufferevent 的選項
  10. enum bufferevent_options options );

buffervent 的選項可以用來改變 bufferevent 的行為。可用的選項包括:

  1. BEV_OPT_CLOSE_ON_FREE
    當 bufferevent 被釋放同時關閉底層(socket 被關閉等)
  2. BEV_OPT_THREADSAFE
    為 bufferevent 自動分配鎖,這樣能夠在多線程環境中安全使用
  3. BEV_OPT_DEFER_CALLBACKS
    當設置了此標志,bufferevent 會延遲它的所有回調(參考前面說的延時回調)
  4. BEV_OPT_UNLOCK_CALLBACKS
    如果 bufferevent 被設置為線程安全的,用戶提供的回調被調用時 bufferevent 的鎖會被持有
    如果設置了此選項,Libevent 將在調用你的回調時釋放 bufferevent 的鎖

建立連接:

  1. // address 和 addrlen 和標準的 connect 函數的參數沒有區別
  2. // 如果 bufferevent bev 沒有設置 socket(在創建時可以設置 socket)
  3. // 那么調用此函數將分配一個新的 socket 給 bev
  4. // 連接成功返回 0 失敗返回 -1
  5. int bufferevent_socket_connect ( struct bufferevent * bev ,
  6. struct sockaddr * address , int addrlen );

簡單的一個范例:

  1. #include <event2/event.h>
  2. #include <event2/bufferevent.h>
  3. #include <sys/socket.h>
  4. #include <string.h>
  5. ?
  6. // 事件回調函數
  7. void eventcb ( struct bufferevent * bev , short events , void * ptr )
  8. {
  9. // 連接成功建立
  10. if ( events & BEV_EVENT_CONNECTED ) {
  11. /* We're connected to 127.0.0.1:8080. Ordinarily we'd do
  12. something here, like start reading or writing. */
  13. // 出現錯誤
  14. } else if ( events & BEV_EVENT_ERROR ) {
  15. /* An error occured while connecting. */
  16. }
  17. }
  18. ?
  19. int main_loop ( void )
  20. {
  21. struct event_base * base ;
  22. struct bufferevent * bev ;
  23. struct sockaddr_in sin ;
  24. ?
  25. base = event_base_new ();
  26. ?
  27. // 初始化連接地址
  28. memset (& sin , 0 , sizeof ( sin ));
  29. sin . sin_family = AF_INET ;
  30. sin . sin_addr . s_addr = htonl ( 0x7f000001 ); /* 127.0.0.1 */
  31. sin . sin_port = htons ( 8080 ); /* Port 8080 */
  32. ?
  33. // 創建一個基于 socket 的 bufferevent
  34. // 參數 -1 表示并不為此 bufferevent 設置 socket
  35. bev = bufferevent_socket_new ( base , - 1 , BEV_OPT_CLOSE_ON_FREE );
  36. ?
  37. // 為 bufferevent bev 設置回調函數
  38. // 這里僅僅設置了事件回調函數
  39. // 后面會詳細談及此函數
  40. bufferevent_setcb ( bev , NULL , NULL , eventcb , NULL );
  41. ?
  42. // 進行連接
  43. if ( bufferevent_socket_connect ( bev ,
  44. ( struct sockaddr *)& sin , sizeof ( sin )) < 0 ) {
  45. /* Error starting connection */
  46. bufferevent_free ( bev );
  47. return - 1 ;
  48. }
  49. ?
  50. // 開始事件循環
  51. event_base_dispatch ( base );
  52. return 0 ;
  53. }

更多的 bufferevent API

釋放 bufferevent

  1. // 如果存在未完成的延時回調,bufferevent 會在回調完成后才被真正釋放
  2. void bufferevent_free ( struct bufferevent * bev );

bufferevent 回調函數的設置和獲取

  1. // 讀取、寫入回調函數原型
  2. // ctx 為用戶自定義數據(由 bufferevent_setcb 設定)
  3. typedef void (* bufferevent_data_cb )( struct bufferevent * bev , void * ctx );
  4. ?
  5. // 事件回調函數原型
  6. // ctx 為用戶自定義數據(由 bufferevent_setcb 設定)
  7. // events 選項可以為:
  8. // BEV_EVENT_READING --- 在 bufferevent 上進行讀取操作時出現了一個事件
  9. // BEV_EVENT_WRITING --- 在 bufferevent 上進行寫入操作時出現了一個事件
  10. // BEV_EVENT_ERROR --- 進行 bufferevent 操作時(例如調用 bufferevent API)出錯,獲取詳細的錯誤信息使用 EVUTIL_SOCKET_ERROR()
  11. // BEV_EVENT_TIMEOUT --- 在 bufferevent 上出現了超時
  12. // BEV_EVENT_EOF --- 在 bufferevent 上遇到了文件結束符
  13. // BEV_EVENT_CONNECTED --- 在 bufferevent 上請求連接完成了
  14. typedef void (* bufferevent_event_cb )( struct bufferevent * bev , short events , void * ctx );
  15. ?
  16. // 設置回調函數
  17. // 如果希望禁用回調函數,那么設置對應的參數為 NULL
  18. void bufferevent_setcb (
  19. // bufferevent
  20. struct bufferevent * bufev ,
  21. // 讀取回調函數
  22. bufferevent_data_cb readcb ,
  23. // 寫入回調函數
  24. bufferevent_data_cb writecb ,
  25. // 事件回調函數
  26. bufferevent_event_cb eventcb ,
  27. // 用戶定義的數據
  28. // 這三個回調函數均共享此參數
  29. void * cbarg
  30. );
  31. ?
  32. // 取回回調函數
  33. // 參數為 NULL 表示忽略
  34. void bufferevent_getcb (
  35. struct bufferevent * bufev ,
  36. bufferevent_data_cb * readcb_ptr ,
  37. bufferevent_data_cb * writecb_ptr ,
  38. bufferevent_event_cb * eventcb_ptr ,
  39. void ** cbarg_ptr
  40. );

設置 watermark

  1. // events 參數可以為
  2. // EV_READ 表示設置 read watermark
  3. // EV_WRITE 表示設置 write watermark
  4. // EV_READ | EV_WRITE 表示設置 read 以及 write watermark
  5. void bufferevent_setwatermark ( struct bufferevent * bufev , short events ,
  6. size_t lowmark , size_t highmark );

獲取到輸入和輸出 buffer

  1. // 獲取到輸入 buffer
  2. struct evbuffer * bufferevent_get_input ( struct bufferevent * bufev );
  3. // 獲取到輸出 buffer
  4. struct evbuffer * bufferevent_get_output ( struct bufferevent * bufev );

添加數據到輸出 buffer

  1. // 下面兩個函數執行成功返回 0 失敗返回 -1
  2. ?
  3. // 向 bufev 的輸出 buffer 中添加大小為 size 的數據
  4. // 數據的首地址為 data
  5. int bufferevent_write ( struct bufferevent * bufev ,
  6. const void * data , size_t size );
  7. // 向 bufev 的輸出 buffer 中添加數據
  8. // 數據來源于 buf
  9. // 此函數會清除 buf 中的所有數據
  10. int bufferevent_write_buffer ( struct bufferevent * bufev ,
  11. struct evbuffer * buf );

從輸入 buffer 中獲取數據

  1. // 從 bufev 的輸入 buffer 中獲取最多 size 字節的數據保存在 data 指向的內存中
  2. // 此函數返回實際讀取的字節數
  3. size_t bufferevent_read ( struct bufferevent * bufev , void * data , size_t size );
  4. // 獲取 bufev 的輸入 buffer 中的所有數據并保存在 buf 中
  5. // 此函數成功返回 0 失敗返回 -1
  6. int bufferevent_read_buffer ( struct bufferevent * bufev ,
  7. struct evbuffer * buf );

關于 bufferevent 的一些高級話題,可以參考: http://www.wangafu.net/~nickm/libevent-book/Ref6a_advanced_bufferevents.html

evbuffers

evbuffer 是一個隊列,在其尾部添加數據和在其頭部刪除數據均被優化了。evbuffer 相關的 API 在這里可以查看: http://www.wangafu.net/~nickm/libevent-book/Ref7_evbuffer.html

Libevent(4)— Bufferevent


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 亚洲一区二区三区在线播放 | 日本一本久道 | 老司机午夜免费精品视频 | 一区二区中文 | 极品xxxx欧美一区二区 | 精品欧美一区二区vr在线观看 | 午夜精品久久久久久久男人的天堂 | 久草网址| 91成人短视频 | 国产精品1区 | 九色 在线| 精品国产一区二区三区久久 | 成人免播放器午夜视频 | 精品久久久爽爽久久久AV | 999久久久精品视频在线观看 | 美日韩免费视频 | 草逼com | 色黄视频在线观看 | 日韩一区精品视频 | 色悠久久久久综合网伊人男男 | 一级黄色免费片 | 亚洲最大视频网站 | 欧美激情精品久久久久久黑人 | 国内自拍偷拍网 | 伊人精品国产 | 99热99色 | 久久亚洲春色中文字幕久久 | 亚洲高清一区二区三区 | 午夜资源| 精品无码国产一区二区日本 | 国产精品午夜电影 | 91在线 | 精品推荐国产麻豆剧传媒 | 国产亚洲一区二区三区在线观看 | 欧美桃色视频 | 香蕉国产人午夜视频在线观看 | 午夜剧场在线免费观看 | 日本欧美一区二区三区视频 | 亚洲一区二区三区免费视频 | 在线久草| 看亚洲a级一级毛片 |