libevent源码IV--bufferevent概念

bufferevent基础和概念

Libevent为这种带缓存的IO模式提供了一个通用的机制。一个”bufferevent”包含一个底层传输(比如socket),一个读buffer和一个写buffer。当底层传输可读写时就调用回调函数,这是普通事件的处理,而bufferevent是在读或写足够的数据时才调用用户指定的回调函数。

每个bufferevent都有一个输入缓存和一个输出缓存,对应的数据结构为struct evbuffer。当你对一个bufferevent写数据,数据写入到输出缓存;当有数据可读时,你是从输入缓存中提取数据。

使用基于socket的bufferevent

基于socket的bufferevent使用起来最简单。基于socket的bufferevent使用Libevent的底层事件机制来检测底层网络socket是否可读写,也使用底层网络调用(比如readv,writev,WSASend,或者WSARecv)来传输和接收数据。

使用bufferevent_socket_new()来创建。接口如下:

struct bufferevent *bufferevent_socket_new(
    struct event_base *base,
    evutil_socket_t fd,
    enum bufferevent_options options);

base是event_base,options是bufferevent标志的位掩码(BEV_OPT_CLOSE_ON_FREE等)。而fd则是可选的socket fd,如果你想稍后再设置fd,可以传-1。

bufferevent可选的标志

在创建一个bufferevent时你可以使用一个或多个标志。可用的标志有:

  1. BEV_OPT_CLOSE_ON_FREE
    当bufferevent被释放时,关闭底层传输。这会关闭一个底层的socker,释放一个底层的bufferevent等。
  2. BEV_OPT_THREADSAFE
    自动为bufferevent分配锁,所以可安全用于多线程。
  3. BEV_OPT_DEFER_CALLBACKS
    如果设置了这个标志,bufferevent推迟所有回调的执行,如上所述。
  4. BEV_OPT_UNLOCK_CALLBACKS
    默认上若一个bufferevent设置成线程安全,则当用户提供的回调调用时会获取该bufferevent的锁。设置这个标志来让Libevent在完成你的回调函数后释放bufferevent的锁。

提示: 确保你提供的socket是非阻塞模式的,Libevent提供了一个便捷的函数evutil_make_socket_nonblocking()来设置一个socket为非阻塞。

如果成功,这个函数返回一个bufferevent,如果失败,返回NULL。

在bufferevent上启用连接

如果bufferevent的socket还没连接,你可以创建一个连接,接口:

int bufferevent_socket_connect(struct bufferevent *bev,
    struct sockaddr *address, int addrlen);

参数addressaddrlen跟标准的connect()一样。如果bufferevent还没有一个socker,调用这个函数会为它创建一个新的socket,并设置socket为非阻塞。

如果bufferevent已经有一个socket,调用bufferevent_socket_connect()告诉Libevent该socket未连接,在连接成功之前不会有读或写操作返回。

在连接返回前向输出buffer添加数据则是可以的。

如果连接成功建立,这个函数返回0,如果出现错误,返回-1。

参考:http://popozhu.github.io/2013/06/26/libevent_r5_bufferevent%E5%9F%BA%E7%A1%80%E5%92%8C%E6%A6%82%E5%BF%B5/

https://blog.csdn.net/luotuo44/article/details/39670221

猜你喜欢

转载自blog.csdn.net/weixin_42169029/article/details/85273951