libevent原始碼IV--bufferevent概念
bufferevent基礎和概念
Libevent為這種帶快取的IO模式提供了一個通用的機制。一個”bufferevent”包含一個底層傳輸(比如socket),一個讀buffer和一個寫buffer。當底層傳輸可讀寫時就呼叫回撥函式,這是普通事件的處理,而bufferevent是在讀或寫足夠的資料時才呼叫使用者指定的回撥函式。
每個bufferevent都有一個輸入快取和一個輸出快取,對應的資料結構為struct evbuffer
。當你對一個bufferevent寫資料,資料寫入到輸出快取;當有資料可讀時,你是從輸入快取中提取資料。
使用基於socket的bufferevent
基於socket的bufferevent使用起來最簡單。基於socket的bufferevent使用Libevent的底層事件機制來檢測底層網路socket是否可讀寫,也使用底層網路呼叫(比如readv,writev,WSASend,或者WSARecv)來傳輸和接收資料。
使用bufferevent_socket_new()
來建立。介面如下:
struct bufferevent *bufferevent_socket_new(
struct event_base *base,
evutil_socket_t fd,
enum bufferevent_options options);
base
是event_base,options
是bufferevent標誌的位掩碼(BEV_OPT_CLOSE_ON_FREE等)。而fd
則是可選的socket fd,如果你想稍後再設定fd,可以傳-1。
bufferevent可選的標誌
在建立一個bufferevent時你可以使用一個或多個標誌。可用的標誌有:
- BEV_OPT_CLOSE_ON_FREE
當bufferevent被釋放時,關閉底層傳輸。這會關閉一個底層的socker,釋放一個底層的bufferevent等。 - BEV_OPT_THREADSAFE
自動為bufferevent分配鎖,所以可安全用於多執行緒。 - BEV_OPT_DEFER_CALLBACKS
如果設定了這個標誌,bufferevent推遲所有回撥的執行,如上所述。 - BEV_OPT_UNLOCK_CALLBACKS
預設上若一個bufferevent設定成執行緒安全,則當用戶提供的回撥呼叫時會獲取該bufferevent的鎖。設定這個標誌來讓Libevent在完成你的回撥函式後釋放bufferevent的鎖。
提示: 確保你提供的socket是非阻塞模式的,Libevent提供了一個便捷的函式evutil_make_socket_nonblocking()
來設定一個socket為非阻塞。
如果成功,這個函式返回一個bufferevent,如果失敗,返回NULL。
在bufferevent上啟用連線
如果bufferevent的socket還沒連線,你可以建立一個連線,介面:
int bufferevent_socket_connect(struct bufferevent *bev,
struct sockaddr *address, int addrlen);
引數address
和addrlen
跟標準的connect()
一樣。如果bufferevent還沒有一個socker,呼叫這個函式會為它建立一個新的socket,並設定socket為非阻塞。
如果bufferevent已經有一個socket,呼叫bufferevent_socket_connect()
告訴Libevent該socket未連線,在連線成功之前不會有讀或寫操作返回。
在連線返回前向輸出buffer新增資料則是可以的。
如果連線成功建立,這個函式返回0,如果出現錯誤,返回-1。