Libevent bufferevent socket flush

时间:2013-08-17 12:41:32

标签: c++ c asynchronous libevent

我会保持简短。如何以阻塞方式将bufferevent输出缓冲区中等待的数据直接刷新到套接字。

在进行异步写入(使用evbuffer_add)后关闭我的套接字包装类时,libevent会发出epoll错误,表示尝试写入无效的fd。我需要能够将待处理的libevent数据刷新到套接字,任何建议吗?

注意:具体错误是fd 9上的Epoll MOD(4)失败。旧事件是6;读取更改为2(del);写入更改为0(无):错误的文件描述符。

3 个答案:

答案 0 :(得分:2)

您是否尝试过禁用套接字延迟?禁用套接字延迟会导致套接字在关闭套接字之前不等待未发送的数据。

struct linger linger;
memset(&linger, 0, sizeof(struct linger));
retVal = setsockopt(sock, SOL_SOCKET, SO_LINGER, (const void*)&linger, sizeof(struct linger));

答案 1 :(得分:2)

对于任何可能遇到同样错误的人,我发现我的问题是什么 - 感谢Inge Henriksen。

class ASocket
{

    // ...

    ~ASocket()
    {
        if(m_handle.bev)
        {
            bufferevent_free(m_handle.bev);
        }

        if(m_handle.fd >= 0)
            ::close(m_handle.fd);
    }

    // ...
}

删除异步套接字对象(ASocket)后,bufferevent将被释放(如果它存在且套接字将被删除) - libevent将继续在已关闭的套接字上运行。请注意,bufferevent_free(如http://www.wangafu.net/~nickm/libevent-book/Ref6_bufferevent.html#_freeing_a_bufferevent所述,但未在Doxygen文档页面上说明)在调用bufferevent函数时不会释放bufferevent_free,而是:

  

然而,bufferevent_free()函数会尝试尽快释放bufferevent。

这是固定的:

class ASocket
{

    // ...

    // If bufferevent exists, it must be created with
    // the BEV_OPT_CLOSE_ON_FREE flag.
    ~ASocket()
    {
        if(m_handle.bev)
        {
            bufferevent_free(m_handle.bev);
        }
        else
        {

            if(m_handle.fd >= 0)
                ::close(m_handle.fd);
        }
    }

    // ...
}

如果套接字有bufferevent,它将被释放,libevent将在套接字完成后关闭套接字。

答案 2 :(得分:0)

我无法在回调本身内执行此操作,但可以使用其他回调来执行此操作,请参阅https://github.com/libevent/libevent/blob/master/sample/le-proxy.c

if (partner) {
                    /* Flush all pending data */
                    readcb(bev, ctx);

                    if (evbuffer_get_length(
                                bufferevent_get_output(partner))) {
                            /* We still have to flush data from the other
                             * side, but when that's done, close the other
                             * side. */
                            bufferevent_setcb(partner,
                                NULL, close_on_finished_writecb,
                                eventcb, NULL);
                            bufferevent_disable(partner, EV_READ);
                    } else {
                            /* We have nothing left to say to the other
                             * side; close it. */
                            bufferevent_free(partner);
                    }
             }