2011-09-03 116 views
5

所以我做了一個使用boost :: asio庫進行異步讀寫的套接字類。它有效,但我有幾個問題。boost :: asio異步操作和資源

這是一個基本的代碼示例:

class Socket 
{ 
public: 
    void doRead() 
    { 
     m_sock->async_receive_from(boost::asio::buffer(m_recvBuffer), m_from, boost::bind(&Socket::handleRecv, this, boost::asio::placeholders::error(), boost::asio::placeholders::bytes_transferred())); 
    } 

    void handleRecv(boost::system::error_code e, int bytes) 
    { 
     if (e.value() || !bytes) 
     { 
      handle_error(); 
      return; 
     } 
     //do something with data read 
     do_something(m_recvBuffer); 

     doRead(); //read another packet 
    } 

protected: 
    boost::array<char, 1024> m_recvBuffer; 
    boost::asio::ip::udp::endpoint m_from; 
}; 

看來,該方案將讀取的數據包,處理它,然後準備讀取另一個。簡單。 但是如果我設置了一個線程池呢?在處理讀取數據之前或之後,是否應該致電doRead()?看起來,如果它放在do_something()之前,程序可以立即開始讀取另一個數據包,如果它被放在後面,該線程會被綁定,不管做什麼do_something(),這可能需要一段時間。如果我在處理之前放置了doRead(),那麼這是否意味着m_readBuffer中的數據可能會在我處理它時發生變化?

此外,如果我使用async_send_to(),我應該將要發送的數據複製到臨時緩衝區中,因爲實際的發送可能在數據超出範圍之後纔會發生?即

void send() 
{ 
    char data[] = {1, 2, 3, 4, 5}; 
    m_sock->async_send_to(boost::buffer(&data[0], 5), someEndpoint, someHandler); 
} //"data" gets deallocated, but the write might not have happened yet! 

另外,當插座被關閉時,handleRecv將具有指示它被中斷的錯誤調用。如果我做

Socket* mySocket = new Socket()... 
... 
mySocket->close(); 
delete mySocket; 

它可能導致一個錯誤,因爲有一個機會,mySockethandleRecv()之前被刪除被調用/完成了嗎?

+0

對於一個很好的問題+1,但是在將來我會建議將它分成Stackoverflow上的單獨問題。 –

回答

2

很多問題在這裏,我會盡量一次解決它們。

但是如果我設置了一個線程池呢?

與Boost.Asio一起使用線程池的傳統方法是調用io_service::run()from multiple threads。請注意,這不是一個普遍適用的答案,但可能存在可伸縮性或性能問題,但這種方法是迄今爲止最容易實現的方法。 Stackoverflow上有許多類似questions的更多信息。

下次調用doRead應該在處理讀取的 數據之前還是之後?看起來如果把它放在do_something()之前,程序 可以立即開始讀取另一個數據包,如果它被放在後面, 這個線程就會被do_something做什麼,可能需要一段時間。

這真的取決於do_something()需要做什麼m_recvBuffer。如果您想使用io_service::post()並行調用do_something()doRead(),您可能需要複製m_recvBuffer

如果我在處理之前放置了doRead(),那麼意味着m_readBuffer中的數據可能會在我處理它時發生變化?

正如我前面提到的,是的,這是可以和將會發生的。

而且,如果我使用async_send_to(),我應該複製發送 到一個臨時緩衝區中的數據,因爲實際的發送可能不會發生 ,直到數據已經下降超出範圍後?

作爲documentation describes,由調用者(您)確保緩衝區在異步操作期間保持在作用域內。如您所懷疑的,您當前的示例調用未定義的行爲,因爲data[]將超出範圍。

另外,當插座被關閉時,handleRecv()將具有指示它被中斷的錯誤稱爲 。

如果您希望繼續使用該套接字,請使用cancel()interrupt outstanding異步操作。否則,close()將工作。在任一情況下傳遞給未完成的異步操作的錯誤是boost::asio::error::operation_aborted