2011-06-28 2 views
1

私は現在、(1)cinからのデータを受け取り、その入力をUNIXソケット経由で送信し、(2)UNIXソケットでデータを受け取り、そのデータを解析し、応答を返すために非同期IOを使用するサーバーを持っています。非同期io_machine内でブロックI/Oを使用できますか?

データを解析するとき、パーサーで発生するI/Oをブロックするにはどうすればよいですか(下の例のParseJSON(data_.data()))?それはparsedasync_writeに返す前に、質問をし、それらの質問に対する回答をcin経由で収集する必要があります。現在、質問は印刷されていますが、答えがcinに入力される前に応答が送信されます。

socket_は、stream_protocol::socketからboost::asioまで、FWIWである。

void handle_read(const boost::system::error_code& error, 
       size_t bytes_transferred) 
{ 
    if (!error) 
    { 
     string parsed = ParseJSON(data_.data()); 
     async_write(socket_, 
      buffer(parsed), 
      boost::bind(&session::handle_write, 
       shared_from_this(), 
       placeholders::error)); 
    } 
} 

void handle_write(const boost::system::error_code& error) 
{ 
    if (!error) 
    { 
     socket_.async_read_some(buffer(data_), 
      boost::bind(&session::handle_read, 
       shared_from_this(), 
       placeholders::error, 
       placeholders::bytes_transferred)); 
    } 
} 

ParseJSONで何が起こるかの省略版(機密保持のための<に置き換えいくつかの文字列>):ことを意味し、それはブロックしますcinから読み取るブロッキングを行い

string ParseJSON(string input) 
{ 
    int status; 
    string toWrite; 

    JSONNode parsed = libjson::parse(input); 
    JSONNode::const_iterator iter = parsed.begin(); 
    json_string node_name = iter -> as_string(); 

    if (node_name.compare("<>") == 0) 
    { 
     cout << "<>" << endl; 
     cout << "<>"; 
     cout.flush(); 
     cin >> status; 

     JSONNode n(JSON_NODE); 
     n.push_back(JSONNode("<>","<>")); 
     JSONNode c(JSON_NODE); 
     c.set_name("args"); 
     c.push_back(JSONNode("<>",status)); 
     n.push_back(c); 
     toWrite = n.write(); 
     return toWrite; 
    } 
} 
+1

'ParseJSON'コールで入出力を扱うコードを表示してください。たとえば' cin >> 'を使用している場合は、入力があるまで「ブロック」します。 – Nim

答えて

1

ParseJSON()場合handle_read()ウォンParseJSON()が返るまでasync_write()を実行してください。

私は問題はparsedがスタック変数であると思います。データが実際に書き込まれる前にhandle_read()が返され、parsedが破棄されます。 async_write()に渡されたデータは、完了ハンドラ(handle_write)が呼び出されるまで有効である必要があります。

handle_read()およびhandle_write()がメンバー関数の場合、parsedメンバーを追加してデータを保持できます。また、あなたはこのようhandle_write()何かにバインドされているのshared_ptrにparsedをラップすることができます:

void handle_read(const boost::system::error_code& error, 
       size_t bytes_transferred) 
{ 
    if (!error) 
    { 
     string *ps = new string(ParseJSON(data_.data())); 
     boost::shared_ptr<string> pParsed(ps); 
     async_write(socket_, 
      buffer(*pParsed), 
      boost::bind(&session::handle_write, 
       shared_from_this(), 
       pParsed, 
       placeholders::error)); 
    } 
} 

void handle_write(boost::shared_ptr<string> pParsed, 
        const boost::system::error_code& error) 
{ 
    if (!error) 
    { 
     socket_.async_read_some(buffer(data_), 
      boost::bind(&session::handle_read, 
       shared_from_this(), 
       placeholders::error, 
       placeholders::bytes_transferred)); 
    } 
} 

すると完了ハンドラが終了すると、shared_ptrのへの最後の参照が消え、psが破壊されます。

+0

これは問題のように聞こえる...それを修正する方法についてのヒント? –

+0

+1これは問題です。 'std :: string parsed'は自動保存期間を持ち、' ​​async_write'が返った直後にスコープから外れます。 'async_write'の[documentation](http://www.boost.org/doc/libs/1_46_1/doc/html/boost_asio/reference/async_write/overload1.html)は、バッファがどのように完了ハンドラまで有効でなければならないかを記述しますが呼び出されます。 –

関連する問題