Bufferevents
Every bufferevent has an input buffer and an output buffer. These are of type "struct evbuffer". When you have data to write on
a bufferevent, you add it to the output buffer; when a bufferevent has data for you to read, you drain it from the input buffer.git
示例源碼github
每一個bufferevent有兩個數據相關的回調:一個讀取回調和一個寫入回調。默認狀況下,從底層傳輸端口讀取了任意量的數據以後會調用讀取回調;輸出緩衝區中足夠量的數據被清空到底層傳輸端口後寫入回調會被調用。經過調整 bufferevent 的讀取和寫入「水位(watermarks) 」能夠覆蓋這些函數的默認行爲。安全
每一個bufferevent有四個水位:
讀取低水位: 讀取操做使得輸入緩衝區的數據量在此級別或者更高時, 讀取回調將被調用。 默認值爲0, 因此每一個讀取操做都會致使讀取回調被調用。
讀取高水位:輸入緩衝區中的數據量達到此級別後, bufferevent將中止讀取, 直到輸入緩衝區中足夠量的數據被抽取, 使得數據量低於此級別。 默認值是無限, 因此永遠不會由於輸入緩衝區的大小而中止讀取。
寫入低水位: 寫入操做使得輸出緩衝區的數據量達到或者低於此級別時, 寫入回調將被調用。默認值是0,因此只有輸出緩衝區空的時候纔會調用寫入回調。
寫入高水位: bufferevent 沒有直接使用這個水位。它在 bufferevent 用做另一個bufferevent的底層傳輸端口時有特殊意義。 請看後面關於過濾型bufferevent的介紹。網絡
bufferevent也有「錯誤」或者「事件」回調, 用於嚮應用通知非面向數據的事件, 如鏈接已經關閉或者發生錯誤。定義了下列事件標誌:
BEV_EVENT_READING:讀取操做時發生某事件,具體是哪一種事件請看其餘標誌。
BEV_EVENT_WRITING:寫入操做時發生某事件,具體是哪一種事件請看其餘標誌。
BEV_EVENT_ERROR:操做時發生錯誤。關於錯誤的更多信息,請調 用EVUTIL_SOCKET_ERROR()。
BEV_EVENT_TIMEOUT:發生超時。
BEV_EVENT_EOF:遇到文件結束指示。
BEV_EVENT_CONNECTED:請求的鏈接過程已經完成app
bufferevent的選項標誌
建立bufferevent 時可使用一個或者多個標誌修改其行爲。可識別的標誌有:
BEV_OPT_CLOSE_ON_FREE:釋放 bufferevent 時關閉底層傳輸端口。這將關閉底層套接字,釋放底層bufferevent 等。
BEV_OPT_THREADSAFE:自動爲 bufferevent 分配鎖,這樣就能夠安全地在多個線程中使用bufferevent。
BEV_OPT_DEFER_CALLBACKS:設置這個標誌時, bufferevent 延遲全部回調,如上所述。
BEV_OPT_UNLOCK_CALLBACKS:默認狀況下,若是設置 bufferevent 爲線程安全的,則bufferevent 會在調用用戶提供的回調時進行鎖定。設置這個選項會讓libevent在執行回調的時候不進行鎖定。socket
與基於套接字的bufferevent一塊兒工做
基於套接字的bufferevent是最簡單的,它使用libevent的底層事件機制來檢測底層網絡套接字是否已經就緒,能夠進行讀寫操做,而且使用底層網絡調用(如 readv、 writev、WSASend、 WSARecv)來發送和接收數據。ide
示例源碼:https://github.com/wanfeng42/chat函數
接口 ui
struct bufferevent *bufferevent_socket_new(struct event_base *base, evutil_socket_t fd, enum bufferevent_options options);
The base is an event_base, and options is a bitmask of bufferevent options (BEV_OPT_CLOSE_ON_FREE, etc). The fd argument is an optional file descriptor for a socket. You can set fd to -1 if you want to set the file descriptor later.this
/**************************************/
int bufferevent_socket_connect(struct bufferevent *bev, struct sockaddr *address, int addrlen);
The address and addrlen arguments are as for the standard call connect(). If the bufferevent does not already have a socket set,
calling this function allocates a new stream socket for it, and makes it nonblocking.
If the bufferevent does have a socket already, calling bufferevent_socket_connect() tells Libevent that the socket is not connected,
and no reads or writes should be done on the socket until the connect operation has succeeded.
It is okay to add data to the output buffer before the connect is done.
This function returns 0 if the connect was successfully launched, and -1 if an error occurred.
Note that you only get a BEV_EVENT_CONNECTED event if you launch the connect() attempt using bufferevent_socket_connect().
If you call connect() on your own, the connection gets reported as a write.
/**************************************/
void bufferevent_free(struct bufferevent *bev);
This function frees a bufferevent. Bufferevents are internally reference-counted, so if the bufferevent has pending deferred
callbacks when you free it, it won’t be deleted until the callbacks are done.
The bufferevent_free() function does, however, try to free the bufferevent as soon as possible. If there is pending data to write on
the bufferevent, it probably won’t be flushed before the bufferevent is freed.
If the BEV_OPT_CLOSE_ON_FREE flag was set, and this bufferevent has a socket or underlying bufferevent associated with it
as its transport, that transport is closed when you free the bufferevent.
/**************************************/
int bufferevent_flush(struct bufferevent *bufev, short iotype, enum bufferevent_flush_mode state);
Flushing a bufferevent tells the bufferevent to force as many bytes as possible to be read to or written from the underlying
transport, ignoring other restrictions that might otherwise keep them from being written. Its detailed function depends on the
type of the bufferevent.
The iotype argument should be EV_READ, EV_WRITE, or EV_READ|EV_WRITE to indicate whether bytes being read, written, or both should be processed. The state argument may be one of BEV_NORMAL, BEV_FLUSH, or BEV_FINISHED.
BEV_FINISHED indicates that the other side should be told that no more data will be sent; the distinction between BEV_NORMAL
and BEV_FLUSH depends on the type of the bufferevent.
The bufferevent_flush() function returns -1 on failure, 0 if no data was flushed, or 1 if some data was flushed.
/**************************************/
typedef void (*bufferevent_data_cb)(struct bufferevent *bev, void *ctx); typedef void (*bufferevent_event_cb)(struct bufferevent *bev, short events, void *ctx); void bufferevent_setcb(struct bufferevent *bufev, bufferevent_data_cb readcb,
bufferevent_data_cb writecb, bufferevent_event_cb eventcb,
void *cbarg); void bufferevent_getcb(struct bufferevent *bufev, bufferevent_data_cb *readcb_ptr, bufferevent_data_cb *writecb_ptr, bufferevent_event_cb *eventcb_ptr, void **cbarg_ptr);
The bufferevent_setcb() function changes one or more of the callbacks of a bufferevent. The readcb, writecb, and eventcb
functions are called (respectively) when enough data is read, when enough data is written, or when an event occurs.The first
argument of each is the bufferevent that has had the event happen. The last argument is the value provided by the user in the cbarg
parameter of bufferevent_callcb(): You can use this to pass data to your callbacks. The events argument of the event callback is
a bitmask of event flags: see "callbacks and watermarks" above.
You can disable a callback by passing NULL instead of the callback function. Note all the callback functions on a bufferevent
share a single cbarg value, so changing it will affect all of them.
/**************************************/
void bufferevent_enable(struct bufferevent *bufev, short events); void bufferevent_disable(struct bufferevent *bufev, short events);
You can enable or disable the events EV_READ, EV_WRITE, or EV_READ|EV_WRITE on a bufferevent. When reading or
writing is not enabled, the bufferevent will not try to read or write data.
By default, a newly created bufferevent has writing enabled, but not reading.
/**************************************/
void bufferevent_setwatermark(struct bufferevent *bufev,
short events, size_t lowmark,
size_t highmark);
The bufferevent_setwatermark() function adjusts the read watermarks, the write watermarks, or both, of a single bufferevent.
(If EV_READ is set in the events field, the read watermarks are adjusted. If EV_WRITE is set in the events field, the write
watermarks are adjusted.)
A high-water mark of 0 is equivalent to "unlimited".
/**************************************/
struct evbuffer *bufferevent_get_input(struct bufferevent *bufev); struct evbuffer *bufferevent_get_output(struct bufferevent *bufev);
These two functions are very powerful fundamental: they return the input and output buffers respectively.
If writing on the bufferevent was stalled because of too little data (or if reading was stalled because of too much), then adding
data to the output buffer (or removing data from the input buffer) will automatically restart it.
/**************************************/
int bufferevent_write(struct bufferevent *bufev, const void *data,
size_t size); int bufferevent_write_buffer(struct bufferevent *bufev, struct evbuffer *buf);
These functions add data to a bufferevent’s output buffer. Calling bufferevent_write() adds size bytes from the memory at data
to the end of the output buffer. Calling bufferevent_write_buffer() removes the entire contents of buf and puts them at the end of
the output buffer. Both return 0 if successful, or -1 if an error occurred.
/**************************************/
size_t bufferevent_read(struct bufferevent *bufev, void *data, size_t size); int bufferevent_read_buffer(struct bufferevent *bufev, struct evbuffer *buf);
These functions remove data from a bufferevent’s input buffer. The bufferevent_read() function removes up to size bytes
from the input buffer, storing them into the memory at data. It returns the number of bytes actually removed. The bufferevent_read_buffer() function drains the entire contents of the input buffer and places them into buf ; it returns 0 on success and-1 on failure.
/**************************************/
enum evbuffer_eol_style { EVBUFFER_EOL_ANY, EVBUFFER_EOL_CRLF, EVBUFFER_EOL_CRLF_STRICT, EVBUFFER_EOL_LF, EVBUFFER_EOL_NUL }; char *evbuffer_readln(struct evbuffer *buffer,
size_t *n_read_out, enum evbuffer_eol_style eol_style);
Many Internet protocols use line-based formats. The evbuffer_readln() function extracts a line from the front of an evbuffer and
returns it in a newly allocated NUL-terminated string. If n_read_out is not NULL, *n_read_out is set to the number of bytes
in the string returned. If there is not a whole line to read, the function returns NULL. The line terminator is not included in the
copied string.
The evbuffer_readln() function understands 4 line termination formats:
EVBUFFER_EOL_LF
The end of a line is a single linefeed character. (This is also known as "\n". It is ASCII value is 0x0A.)
EVBUFFER_EOL_CRLF_STRICT
The end of a line is a single carriage return, followed by a single linefeed. (This is also known as "\r\n". The ASCII values
are 0x0D 0x0A).
EVBUFFER_EOL_CRLF
The end of the line is an optional carriage return, followed by a linefeed. (In other words, it is either a "\r\n" or a "\n".) This
format is useful in parsing text-based Internet protocols, since the standards generally prescribe a "\r\n" line-terminator,
but nonconformant clients sometimes say just "\n".
EVBUFFER_EOL_ANY
The end of line is any sequence of any number of carriage return and linefeed characters. This format is not very useful; it
exists mainly for backward compatibility.
EVBUFFER_EOL_NUL
The end of line is a single byte with the value 0 — that is, an ASCII NUL.
(Note that if you used event_set_mem_functions() to override the default malloc, the string returned by evbuffer_readln will be
allocated by the malloc-replacement you specified.)
/**************************************/
int evbuffer_add(struct evbuffer *buf, const void *data, size_t datlen); This function appends the datlen bytes in data to the end of buf. It returns 0 on success, and -1 on failure. int evbuffer_add_printf(struct evbuffer *buf, const char *fmt, ...) int evbuffer_add_vprintf(struct evbuffer *buf, const char *fmt, va_list ap);
These functions append formatted data to the end of buf. The format argument and other remaining arguments are handled as if
by the C library functions "printf" and "vprintf" respectively. The functions return the number of bytes appended.
/**************************************/
int evbuffer_drain(struct evbuffer *buf, size_t len); int evbuffer_remove(struct evbuffer *buf, void *data, size_t datlen);
The evbuffer_remove() function copies and removes the first datlen bytes from the front of buf into the memory at data. If there
are fewer than datlen bytes available, the function copies all the bytes there are. The return value is -1 on failure, and is otherwise
the number of bytes copied.
The evbuffer_drain() function behaves as evbuffer_remove(), except that it does not copy the data: it just removes it from the
front of the buffer. It returns 0 on success and -1 on failure.
/**************************************/