2013-08-17 44 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); 
        } 
      }