2017-01-08 32 views
0

私はとTCPの間で通信しています。クライアント&のサーバーアプリケーションはどちらも私によって書かれています。私は最初にboost::asio::readを使用している同期データ読み取りでこれを書いていました。 sync_readは、読み取り操作中にsocket.cancelを実行できないことを除いて、すべて正常に機能しています。これは非常に制約になっています&したがって今私の同期読み取りを変換しようとしていますasync_readメカニズムboost :: asio :: async_readはハンドラ関数をコールバックしません

私の同期読み取りメカニズムは、本当にうまくいきました。私は2回読む。まず、パケットヘッダは、その後かなりうまく機能パケットデータを取得する取得 - > - 私は読者のスレッドlike soにそれを呼び出すクライアント側でthreadから連続的に呼び出されるために使用される機能以上>

size_t Read_Data_Sync(std::vector<unsigned char> & msg_body) { 
    //fetch the header 
    MyMessageHeader msg_header; 
    boost::system::error_code err_code; 
    size_t bytes_received = boost::asio::read(socket, boost::asio::buffer(&msg_header, sizeof(msg_header)), err_code); 

    if (bytes_received <= 0 || err_code) 
    return 0; 

    err_code.clear(); 
    msg_body.resize(msg_header.size); 

    //fetch the body 
    bytes_received = boost::asio::read(socket, boost::asio::buffer(msg_body), err_code); 
    if (bytes_received <= 0 || error_code) 
    return 0; 

    return bytes_received; 
} 

auto data_reader_thread = std::thread {[this] { 
    while(run_thread) { 
     Read_Data_Sync(); 
    } 
}}; 

以下は、私が読んメカニズムを作るために、これを変更しています方法ですasync - >

リーダー・スレッドは、それが今、私は

auto data_reader_thread = std::thread {[this] { 
    while(run_thread) { 
     Read_Data_Async(); 
    } 
}}; 

async方法でデータを読み込む行うためにコード化されてきた別の読み取り機能を呼び出すことを除いて、それは同じまま、私は私のクラスのメンバ変数としてmsg_body & msg_headerを行っています。更新されたロジックは、Read_Data_Asyncがスレッド関数から連続的に呼び出されるということです。 Read_Data_Asyncは、順番に、再び私が今直面しています問題は、そのコールバックHandle_Read_Headerあるmessage_body

void Read_Data_Async() 
{ 
    //firstly read message header 
    MyMessageHeader msg_header; 
    boost::asio::async_read(socket, boost::asio::buffer(&msg_header, sizeof(msg_header)), boost::bind(&TCPSession::Handle_Read_Header, this, 
                              boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); 
} 

void Handle_Read_Header(const boost::system::error_code & error, std::size_t bytes_transferred) 
{ 
    //now read the message body 
    if (!error && bytes_transferred > 0) { 
     boost::asio::async_read(socket, boost::asio::buffer(msg_body), boost::bind(&TCPSession::Handle_Read_Body, this, 
                               boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); 
    } 
    else { 
     cout << "Error: " << error << "\n"; 
    } 
} 


void Handle_Read_Body(const boost::system::error_code & error, std::size_t bytes_transferred) 
{ 
    if (!error && bytes_transferred > 0) { 
     // msg_body has the data read from socket 
    } 
    else if (error != boost::asio::error::eof) { 
     cout << "Error: " << error << "\n"; 
    } 
} 

を受信するハンドラのコールバックを渡してメッセージ本文を読むためにboost::asio::async_readを行い、コールバックとしてHandle_Read_Headerの アドレスを結合boost::asio::async_readを呼び出します決して帰ってこない!私は何をしていますか?私はthis oneのようないくつかの関連記事を見て、私の 問題を解決しようとしていますが、がboost::asio::async_readではないので、io.runを呼び出すことを提案しています。

私の上記のロジックは正しいですか?boost::asio::async_readですか?私のハンドラ関数を呼び戻すにはどうすればよいですか?asioあなたはどこかio_service::run()を実行する必要があります

+0

といくつかのより複雑なループ? – mkaes

+0

私のメインスレッドは 'io_service :: run()'を呼び出し、 'io_service'はメインスレッド上にあります。別のリーダースレッドでこの作業を行うにはどうすればよいですか? –

答えて

1

を¹実際には、非同期IOを行うための全体的なアイデアは、あなたがませを行うことである読み取り/書き込み用に別のスレッドが必要:全二重は、単一のスレッドで完全に可能です。


¹または `io_service`オブジェクトの`の実行を() `呼び出すスレッドrun_one、世論調査やpoll_one

+0

'io_service :: run()'はサーバとの接続も行うメインスレッドで呼び出されます。私はワーカースレッド上で読み込みを呼び出すようにバインドされています。なぜなら、私は高速でデータを継続的に更新するアプリケーションだからです。したがって私はループで読み込みを呼び出すスレッドを持つことになります。私は接続されていない場合、私のリーダーのスレッドでも接続を行う必要がありますか? –

+0

サービス 'run'は完了ハンドラがないとすぐに完了します。最後の操作が完了する前に次の操作を送信するようにしてください。あるいは 'io_service :: work'を使用してください。このサンプルがどのように動作するかは、 – sehe

+0

はこれほど大きな制約ではありませんか?メインスレッドや他のスレッドで 'io_service :: run()'を呼び出すかどうかはどうでしょうか?どのように私はこの作業をワーカースレッド上で連続的に呼び出されるようにすることができますか?誰かが同じ問題に直面していたはずです。 –