2013-08-17 42 views
0

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

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

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

回答

2

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

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

的问题是,libevent的实际上不写的所有数据到插座,数据留在libevents内部缓冲区中,并且截至目前,当数据仍在缓冲区中等待时关闭套接字。我想将libevent缓冲区刷入套接字然后关闭它。禁用套接字延迟不起作用。 – Dylan

+0

我不认为'bufferevent_flush'还可以与网络套接字一起工作,但是你试过了吗? – 2013-08-18 12:16:19

+0

如果'bufferevent_flush()'不起作用,那么我会在创建bufferevent时尝试设置'BEV_OPT_CLOSE_ON_FREE'标志。另外,bufferevents是内部引用计数的,所以如果bufferevent在释放时有待处理的延迟回调,那么在回调完成之前它不会被删除。 – 2013-08-18 12:22:40

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_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关闭套接字。

+0

你应该把这篇文章在你的问题中,只需添加一行称为“更新:”并添加此帖子,然后删除此帖子并接受我的答案。当别人在你面前回答你的问题时,用这个解决方案创建一个新的帖子是不常见的做法。 – 2013-08-20 10:31:34

+0

@IngeHenriksen实际上,它是。自我回答非常好。+1,我将你的“不是答案”标志标记为无效。 – Doorknob

+0

我同情你,并感谢你的帮助,但标记和回答这似乎是反作用,这不是正确的答案,但指出我在正确的方向作为正确的答案。答案甚至没有提及“BEV_OPT_CLOSE_ON_FREE”,即在评论中。如果您更新答案以包含解决方案,我会很乐意接受它。我同意@ Doorknob。 – Dylan

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); 
        } 
      }