bufferevent
接口
//回调声明
typedef void (*bufferevent_data_cb)(struct bufferevent *bev, void *ctx);
typedef void (*bufferevent_event_cb)(struct bufferevent *bev, short what, void *ctx);
//设置回调函数
void bufferevent_setcb(struct bufferevent *bufev,
bufferevent_data_cb readcb, bufferevent_data_cb writecb,
bufferevent_event_cb eventcb, void *cbarg);
对于bufferevent_setcb
来说,
第一个参数是发生事件的bufferevent
,最后一个参数是提供给回调函数的参数,这是所有回调函数所共享。
中间三个参数分别表示读回调,写回调和事件回调(可用来进行错误处理)
正如参数所描述,每个回调由函数指针表示,如果要禁用某个回调则需要将相应位置设置为NULL
int bufferevent_enable(struct bufferevent *bufev, short event);
int bufferevent_disable(struct bufferevent *bufev, short event);
short bufferevent_get_enable(struct bufferevent*bufev);//确定bufferevent上当前启用的事件
可以用来启用或者禁用bufferevent
上面的EV_READ
或者EV_WRITE
事件。
再上篇博文已经提到,该函数底层的操作是调用了event_add
将事件注册到了Reactor
中
没用启用的话,bufferevent
不会试图进行数据读取或者写入。
bufferevent
水位
读取低水位 — 默认0,每个读取操作都会导致回调被调用
读取高水位 — 默认无限,当达到此级别后,bufferevent
将停止读取
写入低水位 — 默认0,写入操作使得输出缓冲区的数据量达到或者低于此级别时,回调被调用。
写入高水位 — 没有直接使用
可以通过
void bufferevent_setwatermark(struct bufferevent *bufev, short events,
size_t lowmark, size_t highmark);
设置水位。对于高水位来说0表示无限,而读取和写入通过EV_READ
和EV_WRITE
来指示
所谓的水位无非是一个阈值,以读为例,低水位表示当数据超过这个水平才会触发callback,高水位表示高过这个水位就会阻塞接收数据(需要drain或者remove数据)
可以通过一个简单的例子来测试这个选项:
void do_accept(evutil_socket_t listener, short event, void *arg)
{
//...
bufferevent_setcb(bev, read_cb, NULL, error_cb, arg);
bufferevent_setwatermark(bev,EV_READ,0,5);//设置水位
bufferevent_enable(bev, EV_READ|EV_WRITE|EV_PERSIST);
}
void read_cb(struct bufferevent *bev, void *arg)
{
printf("in readcb\r\n");
struct evbuffer * input;
input = bufferevent_get_input(bev);
evbuffer_drain(input,2);//回收数据
}
完整代码可以参考gayhub
在do_accept
中,设置低水位为0(代表一有数据触发)高水位为5,表示超过5字节后将停止读取
在read_cb
中,每次回收2bytes的数据,使用netcat
键入数据,如果在read_cb中键入超过5个字节的数据并且不调用evbuffer_drain或者evbuffer_remove
在下次键入时将阻塞。