2011-09-03 27 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が呼び出されます。呼び出されるmySockethandleRecv()前に削除される可能性があるので、私は、それがエラーを引き起こす可能性

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

を行う場合/終了?

+0

+1良い質問がありますが、将来私はそれをStackoverflowの別の質問に分割することをお勧めします。 –

答えて

2

ここではたくさんの質問がありますが、私は一度に1つずつ取り上げようとします。

しかし、スレッドプールを設定するとどうなりますか?

Boost.Asioとスレッドプールを使用する従来の方法は、io_service::run()from multiple threadsを呼び出すことです。しかし、スケーラビリティやパフォーマンスの問題があるかもしれませんが、この方法論ははるかに実装するのが一番簡単です。より多くの情報を持つStackoverflowには多くの同様のquestionsがあります。

データを処理する前または後でdoReadを呼び出す必要がありますか? do_something()の前に置かれていると、プログラム は直ちに別のパケットの読み込みを開始することができ、それが後に置かれていると、 は何かdo_somethingを実行してスレッドが結ばれている可能性があります。

これは実際にはm_recvBufferと何が関係しているかによって異なります。do_something()do_something()doRead()と並行して呼び出したい場合は、のコピーを作成する必要があります。

ハンドリングの前にdoRead()を置くと、 は、処理中にm_readBufferのデータが変更される可能性がありますか?

これは先に述べたとおりです。実際の送信データはスコープの外に落ちた後まで を発生しない可能性があるため、また

、私はasync_send_to()使用している場合、私は一時バッファに を送信するデータは、コピーする必要がありますか?

documentation describesとして、バッファが非同期操作の期間中スコープ内に残っていることを確認するのは、呼び出し元(あなた)の責任です。あなたが疑うように、data[]が範囲外になるので、現在の例では未定義のビヘイビアが呼び出されます。ソケットが閉じられたとき

はさらに、handleRecv()は、それが中断されたことを示すエラーで 呼び出されます。

ソケットを引き続き使用する場合は、cancel()interrupt outstandingの非同期操作を使用してください。そうでない場合は、close()が動作します。どちらのシナリオでも未処理の非同期操作に渡されたエラーはboost::asio::error::operation_abortedです。

関連する問題