关闭

[置顶] libevent多线程使用bufferevent的那些事

标签: libeventbuffereven
2424人阅读 评论(2) 收藏 举报
分类:
void do_accept(struct evconnlistener *listener, evutil_socket_t fd, struct sockaddr *sa, int socklen, void *ctx)
{
    //不使用Nagle算法,选择立即发送数据而不是等待产生更多的数据然后再一次发送
    int optval = 1;
    setsockopt(fd, SOL_SOCKET, TCP_NODELAY, &optval, sizeof(optval));
    struct bufferevent * bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);
    if (NULL == bev)
    {
        return 1;
    }
    bufferevent_setcb(bev, do_read, NULL, NULL, NULL);
    bufferevent_enable(bev, EV_READ);
}

在之前的《libevent使用event事件触发服务端实例》中,do_accept使用的event,这里使用了bufferevent,它们的区别:
1.bufferevent有自己的一套错误触发处理机制,可以在bufferevent_setcb设置错误回调函数,event没有
2.void do_read(struct bufferevent *bev, void *ctx);这是bufferevent的读事件回调函数格式
void do_read(evutil_socket_t fd, short ev, void *ctx);这是event的读事件回调函数格式
对于event回调传过去的参数是套接字,也就是说我们自己要在do_read中做recv操作,并存进数据缓冲中,对于bufferevent回调传过去的是bufferevent事件,看一下bufferevent的结构

struct bufferevent 
{
    struct event_base *ev_base;

    struct event ev_read;
    struct event ev_write;

    struct evbuffer *input;//接收数据缓冲
    struct evbuffer *output;//发送数据缓冲

    struct event_watermark wm_read;
    struct event_watermark wm_write;

    evbuffercb readcb;//读回调函数指针
    evbuffercb writecb;//写回调函数指针
    everrorcb errorcb;//错误回调函数指针
    void *cbarg;

    int timeout_read;   /* in seconds */
    int timeout_write;  /* in seconds */

    short enabled;  /* events that are currently enabled */
};

从结构可以看出来,bufferevent已经帮我们做了接收操作,并存在了缓冲input中,也就是说bufferevent相比较event是多了数据缓冲绑定,我们不需要考虑数据缓冲的事情了。当读事件触发,我们就调用bufferevent_read从input拿数据,一切都是那么轻松。既然bufferevent做了接收处理,当然也会通过recv返回值给我们做了错误回调。但是bufferevent不是线程安全的,具体表现:
1. 当你使用bufferevent发送或者接收数据的时候,同时发生断开情况,你要bufferevent_free,对同一个bufferevent出现的抢占会造成段错误,当然你可以打开libevent的锁机制解决这个问题,那也只是解决这个问题,又会带来另一个问题。现在发送或者接收和释放不冲突了,但是释放断开连接之后还发送数据的话,会造成死锁,锁死在bufferevent的锁里面。
2. 当你为新的连接创建bufferevent加入base里面的时候,另外有一个断开连接要从base里面拿出去,那么会造成对base的抢占段错误。当然event也会存在这个问题,打开libevent的锁是可以解决这个问题的。

对于第一种情况,解决的办法是有的,可以给bufferevent在包装一层,标记一个是否可用选项,释放的时候把标识设为不可用,发送和接收的时候先判断是否可用再操作来避免死锁,也就是说先打开了libevent的锁,然后包装一层之后为了这个标识又要再加一次锁。后来看了memcache源码,发现它没有使用bufferevent,只是使用了event来做触发,后面的所有操作都是围绕着套接字进行的,于是我也乖乖的使用基本套接字来进行所有的操作,毕竟关闭套接字的时候使用套接字发送接收不会崩溃,只是返回一个错误码给我们判断,毕竟关闭套接字之后再发送数据也不会死锁也是返回错误码给我们处理。

2
0
查看评论

libevent学习笔记 一、基础知识

1.   Libevent是什么? Libevent是一个轻量级的开源的高性能的网络库,被众多的开源项目使用,例如大名鼎鼎的memcached等。具有如下的显著的特点:事件驱动,轻量级(和ACE相比的话),跨平台,支持多路的IO复用技术,支持定时器、信号等事件。 2.   L...
  • majianfei1023
  • majianfei1023
  • 2015-06-14 16:27
  • 36494

Libevent使用例子,从简单到复杂

本文从简单到复杂,展示Libevent的使用
  • luotuo44
  • luotuo44
  • 2014-09-29 15:17
  • 28817

LibEvent中文帮助文档

LibEvent中文帮助文档:http://blog.csdn.net/zhouyongku LibEvent快速可移植非阻塞式网络编程
  • zhouyongku
  • zhouyongku
  • 2016-12-02 09:44
  • 4376

网络库libevent、libev、libuv对比

Libevent、libev、libuv三个网络库,都是c语言实现的异步事件库Asynchronousevent library)。 异步事件库本质上是提供异步事件通知(Asynchronous Event Notification,AEN)的。异步事件通知机制就是根据发生的事件,调用相应的回调函...
  • lijinqi1987
  • lijinqi1987
  • 2017-05-05 16:42
  • 9971

Libevent 学习--------(eventop)事件多路分发器

一、事件多路分发器一般使用I/O复用接口。 Libvent中使用eventop 结构作为后端I/O复用的统一接口/** Structure to define the backend of a given event_base. */ struct eventop {
  • jackywgw
  • jackywgw
  • 2017-06-07 16:03
  • 678

libevent实现https服务器

libevent实现https服务器 参考老外服务器代码: + https://github.com/ppelleti/https-example + 确保libevent在2.1.2之上版本。 + 确保系统安装openssl,确保libevent_openssl.s...
  • gaoqingwuma
  • gaoqingwuma
  • 2017-08-30 21:49
  • 1646

libevent源码深度剖析一

libevent源码深度剖析一——序幕张亮 1 前言Libevent是一个轻量级的开源高性能网络库,使用者众多,研究者更甚,相关文章也不少。写这一系列文章的用意在于,一则分享心得;二则对libevent代码和设计思想做系统的、更深层次的分析,写出来,也可供后来者参考。附带一句:Libeve...
  • sparkliang
  • sparkliang
  • 2009-12-07 16:10
  • 129666

Libevent触发模式

问题: 文档说Libevent默认是LT触发的,但这个说法并不完整。 看以下两段代码: 1. 使用struct event的读回调void ev_read_cb(evutil_socket_t fd, short event, void *arg) { char st...
  • u013229693
  • u013229693
  • 2016-08-10 10:16
  • 741

Libevent 编程- 定时器事件(timer event)

Libevent 编程- 定时器事件(timer event)本文介绍Libevent 三种事件之一的定时器事件。 该事件可以用来注册定时事件和周期性事件。Libevent 根据所有定时器事件的最小超时时间来设置系统 I/O 的 timeout 值,当系统I/O 返回时,再激活就绪的定时器事件,如此...
  • u010090316
  • u010090316
  • 2017-04-26 22:33
  • 661

Windows下libevent C++封装类实现

题记windows平台下对于服务器高并发的网络模型选型中,使用libevent是个不错的选择。 本文针对libevent从服务端、客户端两个角度实现了封装类,真正做到,我们在使用封装类时候,只需要关注业务逻辑的处理,不需要关注socket的通信的细节。1. Libevent介绍[维基百科]libe...
  • wojiushiwo987
  • wojiushiwo987
  • 2016-12-11 22:15
  • 4058