//libevent笔记-bufferevent带buffer的事件 //转载请注明出处: yuliying的csdn博客. //封装了libevent的一些底层功能,如果不使用bufferevent,当网络读写事件发生时,用户需要自己将 //数据写入read buffer,并自己发送write buffer的数据到网络. bufferevent 代替用户做了这些事情, //用户只需要一心处理read buffer收到的数据,并将要发送的数据写入write buffer , 框架会自动帮我们 //收发这些数据. //bufferevent目前只支持TCP协议, UDP目前还不支持. //每个bufferevent结构体都带有两个evbuffer结构体,分别表示一个socket连接的读buffer和写buffer. //当你要发数据到客户端时,将数据添加到写buffer,读取客户端的数据时从读buffer里拿数据处理. //每个bufferevent有四个水位,水位的设置决定了读写回调函数被调用的时机和网络数据的读写: //1.读低水位(Read low-water mark): // 每当从网络读到数据之后,读buffer的容量大于或等于这个数值的时候,读回调函数被调用. // 默认为0,所以每次读到数据读回调函数都会被调用. //2.读高水位(Read high-water mark): // 如果读buffer的数据量达到这个水位,则会停止从网络读取数据,直到数据被我们处理. //3.写低水位: // 当写数据到网路之后,写buffer的数据量低于这个值,写回调函数被调用. // 默认为零,则在写buffer的数据被完全写到网络之后为空的时候调用写回调函数. //4.写高水位: // 暂时没有直接用处. //每个bufferevent有两个数据相关的回调函数,读回调和写回调. //读回调函数在每次从网络读到数据并且数据量>=读低水位的时候被调用. //写回调函数在足够多的数据被发送到网络后数据量<=读低水位调用. //bufferevent不仅有读写相关的回调函数,还有事件的回调函数.例如连接关闭或者连接发生错误. //支持以下事件类型: //1.BEV_EVENT_READING : 读事件. //2.BEV_EVENT_WRITING : 写事件. //3.BEV_EVENT_ERROR : 错误事件.关于错误的更多信息,请调用EVUTIL_SOCKET_ERROR() //4.BEV_EVENT_TIMEOUT : 超时事件. //5.BEV_EVENT_EOF : 连接关闭事件. //6.BEV_EVENT_CONNECTED : 连接成功事件.用在异步connect的时候. //回调函数的延迟回调 //默认情况下,bufferevent的回调在相应的条件发生时立即被执行.(evbuffer的回调也是这样的) //在依赖关系复杂的情况下,这种立即调用会制造麻烦.比如说,假如某个回调在evbuffer A空的时候向其中 //移入数据,而另一个回调在evbuffer A满的时候从中取出数据.这些调用都是在栈上发生的, //在依赖关系足够复杂的时候,有栈溢出的风险.要解决此问题,可以请求bufferevent(或者evbuffer)延迟其回调. //条件满足时,延迟回调不会立即调用,而是在event_loop()调用中被排队,然后在普通的事件回调之后执行. //当创建bufferevent时可以指定一些参数,改变bufferevent的行为 //1.BEV_OPT_CLOSE_ON_FREE : 释放bufferevent时关闭底层传输端口。这将关闭底层套接字,释放底层bufferevent等 //2.BEV_OPT_THREADSAFE : 加锁. //3.BEV_OPT_DEFER_CALLBACKS : 延迟回调所有回调函数. //创建一个基于socket套接字的bufferevent.如果想稍后再设置fd,可以先将fd设置为-1. //必须保证fd是非阻塞的,可以用 evutil_make_socket_nonblocking()函数来设置. //struct bufferevent *bufferevent_socket_new(struct event_base *base,evutil_socket_t fd , enum bufferevent_options options); //连接到一个地址,将套接字设置为非阻塞,并且创建bufferevent. //连接成功后会在回调函数进行通知(成功是BEV_EVENT_CONNECTED事件,失败是BEV_EVENT_ERROR事件). //连接成功前可以向写buffer写数据. //int bufferevent_socket_connect(struct bufferevent *bev,struct sockaddr *address, int addrlen); //为bufferevent设置回调函数. //void bufferevent_setcb(struct bufferevent *bufev, // bufferevent_data_cb readcb, bufferevent_data_cb writecb, // bufferevent_event_cb eventcb, void *cbarg); //其中数据回调函数的原型是 //typedef void (*bufferevent_data_cb)(struct bufferevent *bev, void *ctx); //事件回调函数的原型是 //typedef void (*bufferevent_event_cb)(struct bufferevent *bev,short events, void *ctx); //获取/设置/取消bufferevent关注的事件 //short bufferevent_get_enabled(struct bufferevent *bufev); //void bufferevent_enable(struct bufferevent *bufev, short events); //void bufferevent_disable(struct bufferevent *bufev, short events); //可以设置的事件有 EV_READ 和 EV_WRITE , 如果不关注事件,bufferevent将不会读写数据. //bufferevent默认关注EV_WRITE , 但没有关注EV_READ , 不会从网络读数据. //设置bufferevent水位,参数events为EV_READ 或 EV_WRITE. //高水位设置为0表示无限制. //void bufferevent_setwatermark(struct bufferevent *bufev, short events,size_t lowmark, size_t highmark); //获取读buffer和写buffer //struct evbuffer *bufferevent_get_input(struct bufferevent *bufev); //struct evbuffer *bufferevent_get_output(struct bufferevent *bufev); //写数据到写buffer //int bufferevent_write(struct bufferevent *bufev,const void *data, size_t size); //将整个buffer追加到写buffer. //int bufferevent_write_buffer(struct bufferevent *bufev,struct evbuffer *buf); //从读buffer读取数据,并将该部分数据从读buffer移除. //size_t bufferevent_read(struct bufferevent *bufev, void *data, size_t size); //将数据从读buffer移除,并添加到我们提供的buffer里面 //int bufferevent_read_buffer(struct bufferevent *bufev,struct evbuffer *buf); //获取/设置bufferevent的优先级,优先级参考之前笔记的event_base 和 event的优先级设置. //int bufferevent_priority_set(struct bufferevent *bufev, int pri); //int bufferevent_get_priority(struct bufferevent *bufev); //获取/设置文件描述符 //evutil_socket_t bufferevent_getfd(struct bufferevent *bufev); //int bufferevent_setfd(struct bufferevent *bufev, evutil_socket_t fd); //从bufferevent获取event_base //struct event_base *bufferevent_get_base(struct bufferevent *bev); //上锁/解锁.同时锁住相关的读写buffer只有在初始化bufferevent的时候设置了BEV_OPT_THREADSAFE 才有效. //锁是递归的 //void bufferevent_lock(struct bufferevent *bufev); //void bufferevent_unlock(struct bufferevent *bufev); //示例在libevent-evconnlistener一篇笔记中.
最新评论: