我会保持简短。如何以阻塞方式将bufferevent
输出缓冲区中等待的数据直接刷新到套接字。
在进行异步写入(使用evbuffer_add
)后关闭我的套接字包装类时,libevent会抛出epoll
错误,表示有人试图写入无效的fd。我需要能够将挂起的libevent数据刷新到套接字,有什么建议吗?
注意:具体错误是fd 9上的Epoll MOD(4)失败。旧事件为6;读数变化为2(del);写入更改为0(无):文件描述符错误。
您是否尝试禁用套接字延迟?禁用套接字延迟会导致套接字在关闭套接字之前不等待未发送的数据。
struct linger linger;
memset(&linger, 0, sizeof(struct linger));
retVal = setsockopt(sock, SOL_SOCKET, SO_LINGER, (const void*)&linger, sizeof(struct linger));
对于那些可能遇到同样错误的人,我发现了我的问题所在——感谢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/libfevent-book/Ref6_bufferevent.html#_freeing_a_bbufferevent,但不在Doxygen文档页面上,不会在调用bufferevent_free
函数时释放bufferevent
,而是:
但是,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将关闭套接字。
我不能在回调内部完成,但可以使用另一个回调来完成,请参阅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);
}
}