接口
struct bufferevent *bufferevent_socket_new(
struct event_base *base,
evutil_socket_t fd,
enum bufferevent_options options);
base是event_base,options是表示bufferevent選項(xiàng)(BEV_OPT_CLOSE_ON_FREE等)的位掩碼,fd是一個(gè)可選的表示套接字的文件描述符。如果想以后設(shè)置文件描述符,可以設(shè)置fd為-1。
成功時(shí)函數(shù)返回一個(gè)bufferevent,失敗則返回NULL。
bufferevent_socket_new()函數(shù)由2.0.1-alpha版新引入。
5.2 在基于套接字的bufferevent上啟動(dòng)連接
如果bufferevent的套接字還沒(méi)有連接上,可以啟動(dòng)新的連接。
接口
int bufferevent_socket_connect(struct bufferevent *bev,
struct sockaddr *address, int addrlen);
address和addrlen參數(shù)跟標(biāo)準(zhǔn)調(diào)用connect()的參數(shù)相同。如果還沒(méi)有為bufferevent設(shè)置套接字,調(diào)用函數(shù)將為其分配一個(gè)新的流套接字,并且設(shè)置為非阻塞的。
如果已經(jīng)為bufferevent設(shè)置套接字,調(diào)用bufferevent_socket_connect()將告知libevent套接字還未連接,直到連接成功之前不應(yīng)該對(duì)其進(jìn)行讀取或者寫(xiě)入操作。
連接完成之前可以向輸出緩沖區(qū)添加數(shù)據(jù)。
如果連接成功啟動(dòng),函數(shù)返回0;如果發(fā)生錯(cuò)誤則返回-1。
示例
#include <event2/event.h>
#include <event2/bufferevent.h>
#include <sys/socket.h>
#include <string.h>
void eventcb(struct bufferevent *bev, short events, void *ptr)
{
if (events & BEV_EVENT_CONNECTED) {
/* We're connected to 127.0.0.1:8080. Ordinarily we'd do
something here, like start reading or writing. */
} else if (events & BEV_EVENT_ERROR) {
/* An error occured while connecting. */
}
}
int main_loop(void)
{
struct event_base *base;
struct bufferevent *bev;
struct sockaddr_in sin;
base = event_base_new();
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = htonl(0x7f000001); /* 127.0.0.1 */
sin.sin_port = htons(8080); /* Port 8080 */
bev = bufferevent_socket_new(base, -1, BEV_OPT_CLOSE_ON_FREE);
bufferevent_setcb(bev, NULL, NULL, eventcb, NULL);
if (bufferevent_socket_connect(bev,
(struct sockaddr *)&sin, sizeof(sin)) < 0) {
/* Error starting connection */
bufferevent_free(bev);
return -1;
}
event_base_dispatch(base);
return 0;
}
bufferevent_socket_connect()函數(shù)由2.0.2-alpha版引入。在此之前,必須自己手動(dòng)在套接字上調(diào)用connect(),連接完成時(shí),bufferevent將報(bào)告寫(xiě)入事件。
注意:如果使用bufferevent_socket_connect()發(fā)起連接,將只會(huì)收到BEV_EVENT_CONNECTED事件。如果自己調(diào)用connect(),則連接上將被報(bào)告為寫(xiě)入事件。
這個(gè)函數(shù)在2.0.2-alpha版引入。
5.3 通過(guò)主機(jī)名啟動(dòng)連接
常常需要將解析主機(jī)名和連接到主機(jī)合并成單個(gè)操作,libevent為此提供了:
接口
int bufferevent_socket_connect_hostname(struct bufferevent *bev,
struct evdns_base *dns_base, int family, const char *hostname,
int port);
int bufferevent_socket_get_dns_error(struct bufferevent *bev);
這個(gè)函數(shù)解析名字hostname,查找其family類(lèi)型的地址(允許的地址族類(lèi)型有AF_INET,AF_INET6和AF_UNSPEC)。如果名字解析失敗,函數(shù)將調(diào)用事件回調(diào),報(bào)告錯(cuò)誤事件。如果解析成功,函數(shù)將啟動(dòng)連接請(qǐng)求,就像bufferevent_socket_connect()一樣。
dns_base參數(shù)是可選的:如果為NULL,等待名字查找完成期間調(diào)用線(xiàn)程將被阻塞,而這通常不是期望的行為;如果提供dns_base參數(shù),libevent將使用它來(lái)異步地查詢(xún)主機(jī)名。關(guān)于DNS的更多信息,請(qǐng)看第九章。
跟bufferevent_socket_connect()一樣,函數(shù)告知libevent,bufferevent上現(xiàn)存的套接字還沒(méi)有連接,在名字解析和連接操作成功完成之前,不應(yīng)該對(duì)套接字進(jìn)行讀取或者寫(xiě)入操作。
函數(shù)返回的錯(cuò)誤可能是DNS主機(jī)名查詢(xún)錯(cuò)誤,可以調(diào)用bufferevent_socket_get_dns_error()來(lái)獲取最近的錯(cuò)誤。返回值0表示沒(méi)有檢測(cè)到DNS錯(cuò)誤。
示例:簡(jiǎn)單的HTTP v0客戶(hù)端
/* Don't actually copy this code: it is a poor way to implement an
HTTP client. Have a look at evhttp instead.
*/
#include <event2/dns.h>
#include <event2/bufferevent.h>
#include <event2/buffer.h>
#include <event2/util.h>
#include <event2/event.h>
#include <stdio.h>
void readcb(struct bufferevent *bev, void *ptr)
{
char buf[1024];
int n;
struct evbuffer *input = bufferevent_get_input(bev);
while ((n = evbuffer_remove(input, buf, sizeof(buf))) > 0) {
fwrite(buf, 1, n, stdout);
}
}
void eventcb(struct bufferevent *bev, short events, void *ptr)
{
if (events & BEV_EVENT_CONNECTED) {
printf("Connect okay.\n");
} else if (events & (BEV_EVENT_ERROR|BEV_EVENT_EOF)) {
struct event_base *base = ptr;
if (events & BEV_EVENT_ERROR) {
int err = bufferevent_socket_get_dns_error(bev);
if (err)
printf("DNS error: %s\n", evutil_gai_strerror(err));
}
printf("Closing\n");
bufferevent_free(bev);
event_base_loopexit(base, NULL);
}
}
int main(int argc, char **argv)
{
struct event_base *base;
struct evdns_base *dns_base;
struct bufferevent *bev;
if (argc != 3) {
printf("Trivial HTTP 0.x client\n"
"Syntax: %s [hostname] [resource]\n"
"Example: %s www.google.com /\n",argv[0],argv[0]);
return 1;
}
base = event_base_new();
dns_base = evdns_base_new(base, 1);
bev = bufferevent_socket_new(base, -1, BEV_OPT_CLOSE_ON_FREE);
bufferevent_setcb(bev, readcb, NULL, eventcb, base);
bufferevent_enable(bev, EV_READ|EV_WRITE);
evbuffer_add_printf(bufferevent_get_output(bev), "GET %s\r\n", argv[2]);
bufferevent_socket_connect_hostname(
bev, dns_base, AF_UNSPEC, argv[1], 80);
event_base_dispatch(base);
return 0;
}
6 通用bufferevent操作
本節(jié)描述的函數(shù)可用于多種bufferevent實(shí)現(xiàn)。
6.1 釋放bufferevent
接口
void bufferevent_free(struct bufferevent *bev);
這個(gè)函數(shù)釋放bufferevent。bufferevent內(nèi)部具有引用計(jì)數(shù),所以,如果釋放bufferevent時(shí)還有未決的延遲回調(diào),則在回調(diào)完成之前bufferevent不會(huì)被刪除。
如果設(shè)置了BEV_OPT_CLOSE_ON_FREE標(biāo)志,并且bufferevent有一個(gè)套接字或者底層bufferevent作為其傳輸端口,則釋放bufferevent將關(guān)閉這個(gè)傳輸端口。
這個(gè)函數(shù)由libevent 0.8版引入。
6.2 操作回調(diào)、水位和啟用/禁用
接口
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);
bufferevent_setcb()函數(shù)修改bufferevent的一個(gè)或者多個(gè)回調(diào)。readcb、writecb和eventcb函數(shù)將分別在已經(jīng)讀取足夠的數(shù)據(jù)、已經(jīng)寫(xiě)入足夠的數(shù)據(jù),或者發(fā)生錯(cuò)誤時(shí)被調(diào)用。每個(gè)回調(diào)函數(shù)的第一個(gè)參數(shù)都是發(fā)生了事件的bufferevent,最后一個(gè)參數(shù)都是調(diào)用bufferevent_setcb()時(shí)用戶(hù)提供的cbarg參數(shù):可以通過(guò)它向回調(diào)傳遞數(shù)據(jù)。事件回調(diào)的events參數(shù)是一個(gè)表示事件標(biāo)志的位掩碼:請(qǐng)看前面的“回調(diào)和水位”節(jié)。
要禁用回調(diào),傳遞NULL而不是回調(diào)函數(shù)。注意:bufferevent的所有回調(diào)函數(shù)共享單個(gè)cbarg,所以修改它將影響所有回調(diào)函數(shù)。
這個(gè)函數(shù)由1.4.4版引入。類(lèi)型名bufferevent_data_cb和bufferevent_event_cb由2.0.2-alpha版引入。
接口
void bufferevent_enable(struct bufferevent *bufev, short events);
void bufferevent_disable(struct bufferevent *bufev, short events);
short bufferevent_get_enabled(struct bufferevent *bufev);
可以啟用或者禁用bufferevent上的EV_READ、EV_WRITE或者EV_READ | EV_WRITE事件。沒(méi)有啟用讀取或者寫(xiě)入事件時(shí),bufferevent將不會(huì)試圖進(jìn)行數(shù)據(jù)讀取或者寫(xiě)入。
沒(méi)有必要在輸出緩沖區(qū)空時(shí)禁用寫(xiě)入事件:bufferevent將自動(dòng)停止寫(xiě)入,然后在有數(shù)據(jù)等待寫(xiě)入時(shí)重新開(kāi)始。
類(lèi)似地,沒(méi)有必要在輸入緩沖區(qū)高于高水位時(shí)禁用讀取事件:bufferevent將自動(dòng)停止讀取,然后在有空間用于讀取時(shí)重新開(kāi)始讀取。
默認(rèn)情況下,新創(chuàng)建的bufferevent的寫(xiě)入是啟用的,但是讀取沒(méi)有啟用。
可以調(diào)用bufferevent_get_enabled()確定bufferevent上當(dāng)前啟用的事件。
除了bufferevent_get_enabled()由2.0.3-alpha版引入外,這些函數(shù)都由0.8版引入。
接口
void bufferevent_setwatermark(struct bufferevent *bufev, short events,
size_t lowmark, size_t highmark);
bufferevent_setwatermark()函數(shù)調(diào)整單個(gè)bufferevent的讀取水位、寫(xiě)入水位,或者同時(shí)調(diào)整二者。(如果events參數(shù)設(shè)置了EV_READ,調(diào)整讀取水位。如果events設(shè)置了EV_WRITE標(biāo)志,調(diào)整寫(xiě)入水位)
對(duì)于高水位,0表示“無(wú)限”。
這個(gè)函數(shù)首次出現(xiàn)在1.4.4版。
示例
#include <event2/event.h>
#include <event2/bufferevent.h>
#include <event2/buffer.h>
#include <event2/util.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
struct info {
const char *name;
size_t total_drained;
};
void read_callback(struct bufferevent *bev, void *ctx)
{
struct info *inf = ctx;
struct evbuffer *input = bufferevent_get_input(bev);
size_t len = evbuffer_get_length(input);
if (len) {
inf->total_drained += len;
evbuffer_drain(input, len);
printf("Drained %lu bytes from %s\n",
(unsigned long) len, inf->name);
}
}
void event_callback(struct bufferevent *bev, short events, void *ctx)
{
struct info *inf = ctx;
struct evbuffer *input = bufferevent_get_input(bev);
int finished = 0;
if (events & BEV_EVENT_EOF) {
size_t len = evbuffer_get_length(input);
printf("Got a close from %s. We drained %lu bytes from it, "
"and have %lu left.\n", inf->name,
(unsigned long)inf->total_drained, (unsigned long)len);
finished = 1;
}
if (events & BEV_EVENT_ERROR) {
printf("Got an error from %s: %s\n",
inf->name, evutil_socket_error_to_string(EVUTIL_SOCKET_ERROR()));
finished = 1;
}
if (finished) {
free(ctx);
bufferevent_free(bev);
}
}
struct bufferevent *setup_bufferevent(void)
{
struct bufferevent *b1 = NULL;
struct info *info1;
info1 = malloc(sizeof(struct info));
info1->name = "buffer 1";
info1->total_drained = 0;
/*
Here we should set up the bufferevent and make sure it gets
connected
*/
/* Trigger the read callback only whenever there is at least 128 bytes
of data in the buffer. */
bufferevent_setwatermark(b1, EV_READ, 128, 0);
bufferevent_setcb(b1, read_callback, NULL, event_callback, info1);
bufferevent_enable(b1, EV_READ); /* Start reading. */
return b1;
} 6.3 操作bufferevent中的數(shù)據(jù)
如果只是通過(guò)網(wǎng)絡(luò)讀取或者寫(xiě)入數(shù)據(jù),而不能觀察操作過(guò)程,是沒(méi)什么好處的。bufferevent提供了下列函數(shù)用于觀察要寫(xiě)入或者讀取的數(shù)據(jù)。(Reading and writing data from the network does you no good if you can't look at it.Bufferevents give you these methods to give them data to write,and to get the data to read.)
接口
struct evbuffer *bufferevent_get_input(struct bufferevent *bufev);
struct evbuffer *bufferevent_get_output(struct bufferevent *bufev);
這兩個(gè)函數(shù)提供了非常強(qiáng)大的基礎(chǔ):它們分別返回輸入和輸出緩沖區(qū)。關(guān)于可以對(duì)evbuffer類(lèi)型進(jìn)行的所有操作的完整信息,請(qǐng)看下一章。
如果寫(xiě)入操作因?yàn)閿?shù)據(jù)量太少而停止(或者讀取操作因?yàn)樘鄶?shù)據(jù)而停止),則向輸出緩沖區(qū)添加數(shù)據(jù)(或者從輸入緩沖區(qū)移除數(shù)據(jù))將自動(dòng)重啟操作。
這些函數(shù)由2.0.1-alpha版引入。
接口
int bufferevent_write(struct bufferevent *bufev,
const void *data, size_t size);
int bufferevent_write_buffer(struct bufferevent *bufev,
struct evbuffer *buf);
這些函數(shù)向bufferevent的輸出緩沖區(qū)添加數(shù)據(jù)。bufferevent_write()將內(nèi)存中從data處開(kāi)始的size字節(jié)數(shù)據(jù)添加到輸出緩沖區(qū)的末尾。bufferevent_write_buffer()移除buf的所有內(nèi)容,將其放置到輸出緩沖區(qū)的末尾。成功時(shí)這些函數(shù)都返回0,發(fā)生錯(cuò)誤時(shí)則返回-1。
這些函數(shù)從0.8版就存在了。
接口
size_t bufferevent_read(struct bufferevent *bufev, void *data, size_t size);
int bufferevent_read_buffer(struct bufferevent *bufev,
struct evbuffer *buf);
這些函數(shù)從bufferevent的輸入緩沖區(qū)移除數(shù)據(jù)。bufferevent_read()至多從輸入緩沖區(qū)移除size字節(jié)的數(shù)據(jù),將其存儲(chǔ)到內(nèi)存中data處。函數(shù)返回實(shí)際移除的字節(jié)數(shù)。bufferevent_read_buffer()函數(shù)抽空輸入緩沖區(qū)的所有內(nèi)容,將其放置到buf中,成功時(shí)返回0,失敗時(shí)返回-1。
注意,對(duì)于bufferevent_read(),data處的內(nèi)存塊必須有足夠的空間容納size字節(jié)數(shù)據(jù)。
bufferevent_read()函數(shù)從0.8版就存在了;bufferevnet_read_buffer()由2.0.1-alpha版引入。
示例
#include <event2/bufferevent.h>
#include <event2/buffer.h>
#include <ctype.h>
void
read_callback_uppercase(struct bufferevent *bev, void *ctx)
{
/* This callback removes the data from bev's input buffer 128
bytes at a time, uppercases it, and starts sending it
back.
(Watch out! In practice, you shouldn't use toupper to implement
a network protocol, unless you know for a fact that the current
locale is the one you want to be using.)
*/
char tmp[128];
size_t n;
int i;
while (1) {
n = bufferevent_read(bev, tmp, sizeof(tmp));
if (n <= 0)
break; /* No more data. */
for (i=0; i<n; ++i)
tmp[i] = toupper(tmp[i]);
bufferevent_write(bev, tmp, n);
}
}
struct proxy_info {
struct bufferevent *other_bev;
};
void
read_callback_proxy(struct bufferevent *bev, void *ctx)
{
/* You might use a function like this if you're implementing
a simple proxy: it will take data from one connection (on
bev), and write it to another, copying as little as
possible. */
struct proxy_info *inf = ctx;
bufferevent_read_buffer(bev,
bufferevent_get_output(inf->other_bev));
}
struct count {
unsigned long last_fib[2];
};
void
write_callback_fibonacci(struct bufferevent *bev, void *ctx)
{
/* Here's a callback that adds some Fibonacci numbers to the
output buffer of bev. It stops once we have added 1k of
data; once this data is drained, we'll add more. */
struct count *c = ctx;
struct evbuffer *tmp = evbuffer_new();
while (evbuffer_get_length(tmp) < 1024) {
unsigned long next = c->last_fib[0] + c->last_fib[1];
c->last_fib[0] = c->last_fib[1];
c->last_fib[1] = next;
evbuffer_add_printf(tmp, "%lu", next);
}
/* Now we add the whole contents of tmp to bev. */
bufferevent_write_buffer(bev, tmp);
/* We don't need tmp any longer. */
evbuffer_free(tmp);
}
6.4 讀寫(xiě)超時(shí)
跟其他事件一樣,可以要求在一定量的時(shí)間已經(jīng)流逝,而沒(méi)有成功寫(xiě)入或者讀取數(shù)據(jù)的時(shí)候調(diào)用一個(gè)超時(shí)回調(diào)。
接口
void bufferevent_set_timeouts(struct bufferevent *bufev,
const struct timeval *timeout_read, const struct timeval *timeout_write);
設(shè)置超時(shí)為NULL會(huì)移除超時(shí)回調(diào)。
試圖讀取數(shù)據(jù)的時(shí)候,如果至少等待了timeout_read秒,則讀取超時(shí)事件將被觸發(fā)。試圖寫(xiě)入數(shù)據(jù)的時(shí)候,如果至少等待了timeout_write秒,則寫(xiě)入超時(shí)事件將被觸發(fā)。
注意,只有在讀取或者寫(xiě)入的時(shí)候才會(huì)計(jì)算超時(shí)。也就是說(shuō),如果bufferevent的讀取被禁止,或者輸入緩沖區(qū)滿(mǎn)(達(dá)到其高水位),則讀取超時(shí)被禁止。類(lèi)似的,如果寫(xiě)入被禁止,或者沒(méi)有數(shù)據(jù)待寫(xiě)入,則寫(xiě)入超時(shí)被禁止。
讀取或者寫(xiě)入超時(shí)發(fā)生時(shí),相應(yīng)的讀取或者寫(xiě)入操作被禁止,然后超時(shí)事件回調(diào)被調(diào)用,帶有標(biāo)志BEV_EVENT_TIMEOUT | BEV_EVENT_READING或者BEV_EVENT_TIMEOUT | BEV_EVENT_WRITING。
這個(gè)函數(shù)從2.0.1-alpha版就存在了,但是直到2.0.4-alpha版才對(duì)于各種bufferevent類(lèi)型行為一致。
6.5 對(duì)bufferevent發(fā)起清空操作
接口
int bufferevent_flush(struct bufferevent *bufev,
short iotype, enum bufferevent_flush_mode state)
清空bufferevent要求bufferevent強(qiáng)制從底層傳輸端口讀取或者寫(xiě)入盡可能多的數(shù)據(jù),而忽略其他可能保持?jǐn)?shù)據(jù)不被寫(xiě)入的限制條件。函數(shù)的細(xì)節(jié)功能依賴(lài)于bufferevent的具體類(lèi)型。
iotype參數(shù)應(yīng)該是EV_READ、EV_WRITE或者EV_READ | EV_WRITE,用于指示應(yīng)該處理讀取、寫(xiě)入,還是二者都處理。state參數(shù)可以是BEV_NORMAL、BEV_FLUSH或者BEV_FINISHED。BEV_FINISHED指示應(yīng)該告知另一端,沒(méi)有更多數(shù)據(jù)需要發(fā)送了;而B(niǎo)EV_NORMAL和BEV_FLUSH的區(qū)別依賴(lài)于具體的bufferevent類(lèi)型。
失敗時(shí)bufferevent_flush()返回-1,如果沒(méi)有數(shù)據(jù)被清空則返回0,有數(shù)據(jù)被清空則返回1。
當(dāng)前(2.0.5-beta版)僅有一些bufferevent類(lèi)型實(shí)現(xiàn)了bufferevent_flush()。特別是,基于套接字的bufferevent沒(méi)有實(shí)現(xiàn)。
7 類(lèi)型特定的bufferevent函數(shù)
這些bufferevent函數(shù)不能支持所有bufferevent類(lèi)型。
接口
int bufferevent_priority_set(struct bufferevent *bufev, int pri);
int bufferevent_get_priority(struct bufferevent *bufev);
這個(gè)函數(shù)調(diào)整bufev的優(yōu)先級(jí)為pri。關(guān)于優(yōu)先級(jí)的更多信息請(qǐng)看event_priority_set()。
成功時(shí)函數(shù)返回0,失敗時(shí)返回-1。這個(gè)函數(shù)僅能用于基于套接字的bufferevent。
這個(gè)函數(shù)由1.0版引入。
接口
int bufferevent_setfd(struct bufferevent *bufev, evutil_socket_t fd);
evutil_socket_t bufferevent_getfd(struct bufferevent *bufev);
這些函數(shù)設(shè)置或者返回基于fd的事件的文件描述符。只有基于套接字的bufferevent支持setfd()。兩個(gè)函數(shù)都在失敗時(shí)返回-1;setfd()成功時(shí)返回0。
bufferevent_setfd()函數(shù)由1.4.4版引入;bufferevent_getfd()函數(shù)由2.0.2-alpha版引入。
接口
struct event_base *bufferevent_get_base(struct bufferevent *bev);
這個(gè)函數(shù)返回bufferevent的event_base,由2.0.9-rc版引入。
接口
struct bufferevent *bufferevent_get_underlying(struct bufferevent *bufev);
這個(gè)函數(shù)返回作為bufferevent底層傳輸端口的另一個(gè)bufferevent。關(guān)于這種情況,請(qǐng)看關(guān)于過(guò)濾型bufferevent的介紹。
這個(gè)函數(shù)由2.0.2-alpha版引入。
8 手動(dòng)鎖定和解鎖
有時(shí)候需要確保對(duì)bufferevent的一些操作是原子地執(zhí)行的。為此,libevent提供了手動(dòng)鎖定和解鎖bufferevent的函數(shù)。
接口
void bufferevent_lock(struct bufferevent *bufev);
void bufferevent_unlock(struct bufferevent *bufev);
注意:如果創(chuàng)建bufferevent時(shí)沒(méi)有指定BEV_OPT_THREADSAFE標(biāo)志,或者沒(méi)有激活libevent的線(xiàn)程支持,則鎖定操作是沒(méi)有效果的。
用這個(gè)函數(shù)鎖定bufferevent將自動(dòng)同時(shí)鎖定相關(guān)聯(lián)的evbuffer。這些函數(shù)是遞歸的:鎖定已經(jīng)持有鎖的bufferevent是安全的。當(dāng)然,對(duì)于每次鎖定都必須進(jìn)行一次解鎖。
這些函數(shù)由2.0.6-rc版引入。
9 已廢棄的bufferevent功能
從1.4到2.0版,bufferevent的后端代碼一直在進(jìn)行修訂。在老的接口中,訪(fǎng)問(wèn)bufferevent結(jié)構(gòu)體的內(nèi)部是很平常的,并且還會(huì)使用依賴(lài)于這種訪(fǎng)問(wèn)的宏。
更復(fù)雜的是,老的代碼有時(shí)候?qū)?#8220;evbuffer”前綴用于bufferevent功能。
這里有一個(gè)在2.0版之前使用過(guò)的東西的概要:
老的函數(shù)定義在event.h中,而不是在event2/bufferevent.h中。
如果仍然需要訪(fǎng)問(wèn)bufferevent結(jié)構(gòu)體內(nèi)部的某些公有部分,可以包含event2/bufferevent_struct.h。但是不建議這么做:不同版本的Libevent中bufferevent結(jié)構(gòu)體的內(nèi)容可能會(huì)改變。本節(jié)描述的宏和名字只有在包含了event2/bufferevent_compat.h時(shí)才能使用。
較老版本中用于設(shè)置bufferevent的接口有所不同:
接口
struct bufferevent *bufferevent_new(evutil_socket_t fd,
evbuffercb readcb, evbuffercb writecb, everrorcb errorcb, void *cbarg);
int bufferevent_base_set(struct event_base *base, struct bufferevent *bufev);
bufferevent_new()函數(shù)僅僅在已經(jīng)廢棄的“默認(rèn)”event_base上創(chuàng)建一個(gè)套接字bufferevent。調(diào)用bufferevent_base_set()可以調(diào)整套接字bufferevent的event_base。
較老版本不使用timeval結(jié)構(gòu)體設(shè)置超時(shí),而是使用秒數(shù):
接口
void bufferevent_settimeout(struct bufferevent *bufev,
int timeout_read, int timeout_write);
最后要指出的是,2.0之前版本中的evbuffer實(shí)現(xiàn)是極其低效的,這對(duì)將bufferevent用于高性能應(yīng)用是一個(gè)問(wèn)題。