2010-12-29 18 views
20

他のStack Overflowエントリとboost::asioのドキュメントを読んでから、呼び出しのパラメータとして使いやすいタイムアウトを提供する同期ASIO読み書き呼び出しがないことを確認しました。C++ Boost ASIO:タイムアウトで読み書きする方法は?

私は、タイムアウトを使用するselect(2)コールで旧式のLinuxソケットアプリケーションを変換する途中にありますが、それ以上のことをやる必要があります。

boost::asioでこれを行うにはどうすればよいですか? asioドキュメントを見ると、タイマーとはさまざまなものが混乱する例がたくさんありますが、私はかなり混乱しています。 ソケットから読み取っても、関数が何も返さないか、またはできるだけ早く返すことができる最大秒数Xを待ってください。タイムアウトが切れる前にソケットから読み取る。

+3

この例について混乱していることを具体的に説明してください。http://think-async.com/Asio/asio-1.4.7/src/examples/timeouts/blocking_tcp_clientcpp - 不可欠なロジックは、2つの非同期タスクをディスパッチすることです.1つは読み取り/書き込み、もう1つは読み取り/書き込みが最初に戻る場合はタイムアウトタイマーが終了した場合はロジックが読み書きそれでもあなたのタイムアウトロジックを進めてください。非常に非常に簡単です。 –

+2

コールバックのキューイングに関連するhfネットワークで発生するコーナーケースが1つあります。タイムアウトcbがキューに入れられた後、読み書きはキューに入れられます。実際には読み取り/書き込みが完了したときにタイムアウト・ロジックを実行し始めます。私が見た可能な解決策は、ダブル・チェック・ロックに似たものです。つまり、最初のタイムアウトが戻ったときに、しかし、これは2番目のタイムアウトがキューに入った後に読み書きがキューに入れられた場合と同じ問題を抱えています。 –

+2

タイムアウトは厳しい条件であることを覚えておいてください。私は何か具体的なことをするでしょう - これは、読み書きがすでに行われているかもしれないという事実を含み、あなたがまだそれを受け取っていないという事実を変えないということです。 –

答えて

6

これはasioメーリングリストに掲載されており、機能を要求しているのはticketです。要約すると、タイムアウトと取り消しが必要な場合は、非同期メソッドを使用することをお勧めします。


あなたは非同期メソッドに変換できない場合は、SO_RCVTIMEOSO_SNDTIMEOソケットオプションを試してみてください。それらはsetsockoptで設定でき、ディスクリプタはboost::asio::ip::tcp::socket::nativeメソッドで取得できます。 man 7 socket manページは

SO_RCVTIMEOとSO_SNDTIMEO は エラーを報告するまで、受信または送信タイムアウトを指定しますと言います。引数はstruct timevalです。 機能ブロックが のこの期間にブロックされ、データが に送信または受信された場合、その関数の戻り値は、転送されるデータの量である になります。 データが転送されておらず、 のタイムアウトに達した場合、-1が に返され、 に指定された場合と同様に、errnoが EAGAINまたはEWOULDBLOCKに設定されて返されます。タイムアウトが がゼロ(デフォルト)に設定されている場合、 操作は決してタイムアウトしません。 タイムアウトは、ソケットI/Oを実行するシステムコール(例えば、read(2)、 、recvmsg(2)、send(2)、sendmsg(2))の場合にのみ、 となります。 タイムアウトは、私はこれを生成するために、いくつかのasio docsを使用(2)、 ポール(2)、イベントがepoll_wait(2)、等を選択

+1

リクエストに対するCHの応答をお読みになりましたか? ASIOはC++でOS機能を再現しますが、何らかのタイムアウト機能が必要な場合は、ASIOが提供するbit-n-pieceを使用して実装することを歓迎します。 –

5

には影響を及ぼさない。

class TimeoutAdjust 
{ 
public: 
    TimeoutAdjust(unsigned int dwTimeout) : m_dwTimeout(dwTimeout) {}; 

    template<class Protocol> 
    int level(const Protocol& p) const {return SOL_SOCKET;} 

    template<class Protocol> 
    int name(const Protocol& p) const {return SO_SNDTIMEO;} 

    template<class Protocol> 
    const void* data(const Protocol& p) const {return &m_dwTimeout;} 

    template<class Protocol> 
    size_t size(const Protocol& p) const {return sizeof(m_dwTimeout);} 
private: 
    unsigned int m_dwTimeout; 
}; 

使用:

TimeoutAdjust adjust(5000); 
sSocket.set_option(adjust); 

私はそれをデバッグし、それは想定されているように見えます。

+1

私がここで読んだのは、 'SO_SNDTIMEO'は' unsigned int'ではなく 'timeval'です。 http://linux.die.net/man/7/socket – updogliu

+0

ああ、MSのドキュメントはSO_SNDTIMEOのためにDWORDを使用します。 timevalは長いintのペアのように見えるので、読者は注意してください。 MS docs:http://msdn.microsoft.com/en-ca/library/windows/desktop/ms740532(v=vs.85).aspx – ArtHare

+2

上記のコードを使用した後、例外が発生しています。例外:set_option:無効参照コードがある場合は、それを共有してください。 – asim

関連する問題