bufferevent_free 内部是引用计数,他会尽快的关闭,不会立即关闭,判断没有引用了才会关。
如果用bufferevent_write发送后立马调用bufferevent_free可能会导致部分数据(没有引用?)没有发出去(不要过早关闭)。
void socket_eventcb(struct bufferevent *bev, short events, void *user_data){
if (events & BEV_EVENT_EOF) {
bufferevent_free(bev);
} else if (events & BEV_EVENT_ERROR) {
bufferevent_free(bev);
} else if(events & BEV_EVENT_TIMEOUT)
bufferevent_free(bev); //超时事件,规定时间内无响应,关闭客户端连接
//超时时 EV_READ 是disable的,可以通过bufferevent_enable(bev, EV_READ)再把它置为可读,但是一般长时间没有响应都当成连接断开,通过bufferevent_free 释放bev(结合 FREE_ON_CLOSE属性关闭socket连接)
}
void socket_readcb(struct bufferevent *bev, void *user_data){
char buffer[512] = {0};
while(1){
struct evbuffer *input = bufferevent_get_input(bev); //获取读取的evbuffer
int length = evbuffer_get_length(input);
if (length <=0){
bufferevent_write(bev, "ok12345\n", sizeof("ok\n")); //bufferevent 的发送数据方式
return;
}
int getlen = sizeof(buffer) -1;
if(length < getlen){
getlen = length;
}
unsigned int len = evbuffer_remove(input, buffer, getlen);//真正的读取数据并从evbuffer中移除
if(len != getlen){
cerr<<"read data len error:"<<strerror(errno)<<endl;
return;
}
cout<<buffer<<endl;
}
}
void socket_listenercb(struct evconnlistener *listener, evutil_socket_t fd, struct sockaddr *sa, int socklen, void *user_data){
int32_t enable = 1;
setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (const char*) &enable, sizeof(enable));
setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (const char*) &enable, sizeof(enable));
evutil_make_socket_nonblocking(fd);
struct event_base *base = evconnlistener_get_base(listener);
bufferevent *bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);
if (NULL == bev){
return;
}
bufferevent_enable(bev, EV_READ | EV_WRITE | EV_PERSIST);
//当收到字节长度小于低水位值时,不触发回调。当高于高水位值时,分批回调处理
bufferevent_setwatermark(bev, EV_READ, 5, 10); //默认高、低水位值是0,而0表示无限制。
//网上对EV_WRITE的理解不是很准确
bufferevent_setwatermark(bev, EV_WRITE, 5, 30); //并没有测出发送长度不够低水位值时不触发回调,相反是每次最多只能发送4个字节,write的高水位并没有用
timeval t1 = {5, 0} ; //设置read的超时时间
bufferevent_set_timeouts(bev, &t1/*read*/, NULL /*write*/);
bufferevent_setcb(bev, socket_readcb, NULL, socket_eventcb, user_data);
}