0

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

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

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

4

3 回答 3

2

对于任何可能遇到相同错误的人,我发现了我的问题——感谢 Inge Henriksen。

class ASocket
{

    // ...

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

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

    // ...
}

删除异步套接字对象ASocketbufferevent请注意,bufferevent_free,如http://www.wangafu.net/~nickm/libevent-book/Ref6_bufferevent.html#_freeing_a_buffereventbufferevent所述,但不在 Doxygen 文档页面上,在调用该函数时不会释放,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 将关闭套接字。

于 2013-08-19T07:39:27.737 回答
2

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

struct linger linger;
memset(&linger, 0, sizeof(struct linger));
retVal = setsockopt(sock, SOL_SOCKET, SO_LINGER, (const void*)&linger, sizeof(struct linger));
于 2013-08-17T17:51:06.913 回答
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);
                    }
             }
于 2013-12-29T13:12:34.257 回答