处理并发之二:libevent的eventbuffer
bufferevent这个结构体
1 | struct bufferevent { |
可以看出 struct bufferevent 内置了两个 event(读/写)和对应的缓冲区。当有数据被读入(input)的时候,readcb 被调用,当 output 被输出完成的时候,writecb 被调用,当网络 I/O 出现错误,如链接中断,超时或其他错误时,errorcb 被调用。
使用 bufferevent 的过程:
1. 设置sock为非阻塞的
1 | // eg: evutil_make_socket_nonblocking(fd); |
*2. 使用bufferevent_socket_new创建一个structbufferevent bev,关联该sockfd,托管给event_base
函数原型为:
1 | struct bufferevent * bufferevent_socket_new(struct event_base *base, evutil_socket_t fd, int options) |
3. 设置读写对应的回调函数
函数原型为:
1 | void bufferevent_setcb(struct bufferevent *bufev, |
4. 启用读写事件,其实是调用了event_add将相应读写事件加入事件监听队列poll。正如文档所说,如果相应事件不置为true,bufferevent是不会读写数据的
函数原型:
1 | int bufferevent_enable(struct bufferevent *bufev, short event) |
5. 进入bufferevent_setcb回调函数:
在readcb里面从input中读取数据,处理完毕后填充到output中; writecb对于服务端程序,只需要readcb就可以了,可以置为NULL; errorcb 用于处理一些错误信息。
针对这些使用过程进入源码进行分析:
1. bufferevent_socket_new
- 在bufferevent_init_common中调用evbuffer_new()初始化input和output
- 在event_assign中初始化bufferevent中的ev_read和ev_write事件。
- 在evbuffer_add_cb中给output添加了一个callback bufferevent_socket_outbuf_cb
2. bufferevent_setcb
该函数的作用主要是赋值,把该函数后面的参数,赋值给第一个参数 struct bufferevent *bufev
定义的变量
3. bufferevent_enable
调用event_add将读写事件加入到事件监听队列中。
对bufferevent常用的几个函数进行分析:
1 | char *evbuffer_readln(struct evbuffer*buffer, size_t *n_read_out,enum |
1 | int evbuffer_add(struct evbuffer *buf,const void *data, size_t datlen); |
1 | int evbuffer_remove(struct evbuffer*buf, void *data, size_t datlen); |
1 | size_t evbuffer_get_length(const structevbuffer *buf); |
暂时先分析到这里,下面是代码,客户端发送消息:
1 | HTTP/1.0, Client 0 send Message: |
服务端一条消息收完成后,会回复:
1 | Response ok! Hello Client! |
服务端从bufferevent中取出消息是按行取的。代码可能有不完善的地方,由于才疏学浅,研究时间短(3天),希望高手提出宝贵意见。
buffer_server.c
1 |
|