41

保留中の操作を (切断せずに) キャンセルする方法、またはブースト ライブラリ関数のタイムアウトを設定する方法はありますか?

つまり、boost asio でソケットをブロックする際にタイムアウトを設定したいですか?

socket.read_some(boost::asio::buffer(pData, maxSize), error_);

例: ソケットからいくつか読み取りたいが、10 秒経過したらエラーを発生させたい。

4

9 に答える 9

23

この質問がされたとき、ASIO には、OP が必要とすることを達成する方法、つまりブロッキング ソケット操作などのブロッキング操作をタイムアウトにする方法の例がなかったと思います。これを行う方法を正確に示す例があります。この例は長いように見えますが、それは WELL コメントが付けられているためです。「ワンショット」モードで ioservice を使用する方法を示します。

例は素晴らしい解決策だと思います。ここでの他のソリューションは移植性を壊し、ioservice を利用しません。移植性が重要ではなく、ioservice のオーバーヘッドが大きいように思われる場合は、ASIO を使用しないでください。いずれにせよ、ioservice が作成されるので (ほとんどすべての ASIO 機能がそれに依存し、同期ソケットも含まれます)、それを利用してください。

ブロッキング asio tcp 操作のタイムアウト

ブロッキング asio udp 操作のタイムアウト

ASIO のドキュメントが更新されたので、ASIO が使用する「落とし穴」のいくつかを克服する方法に関する新しい例を確認してください。

于 2012-12-28T02:57:56.210 に答える
10

async_readを実行し、希望するタイムアウトのタイマーを設定することもできます。次に、タイマーが起動した場合は、ソケットオブジェクトでcancelを呼び出します。それ以外の場合、読み取りが発生した場合は、タイマーをキャンセルできます。もちろん、これにはio_serviceオブジェクトを使用する必要があります。

編集:これを行うコードスニペットを見つけました

http://lists.boost.org/Archives/boost/2007/04/120339.php

于 2008-11-26T02:41:24.533 に答える
9

私は同じ質問をしていましたが、いくつかの調査の結果、私が思いついた最も単純でクリーンな解決策は、基礎となるネイティブ ソケットを取得し、読み取るデータが存在するまで選択を行うことでした。Select はタイムアウト パラメータを受け取ります。もちろん、ネイティブ ソケットを使用することは、そもそも asio を使用するという点に反し始めますが、繰り返しますが、これが最もクリーンな方法のようです。私が知る限り、asio は同期使用のためにこれを簡単に行う方法を提供していません。コード:

        // socket here is:  boost::shared_ptr<boost::asio::ip::tcp::socket> a_socket_ptr

        // Set up a timed select call, so we can handle timeout cases.

        fd_set fileDescriptorSet;
        struct timeval timeStruct;

        // set the timeout to 30 seconds
        timeStruct.tv_sec = 30;
        timeStruct.tv_usec = 0;
        FD_ZERO(&fileDescriptorSet);

        // We'll need to get the underlying native socket for this select call, in order
        // to add a simple timeout on the read:

        int nativeSocket = a_socket_ptr->native();

        FD_SET(nativeSocket,&fileDescriptorSet);

        select(nativeSocket+1,&fileDescriptorSet,NULL,NULL,&timeStruct);

        if(!FD_ISSET(nativeSocket,&fileDescriptorSet)){ // timeout

                std::string sMsg("TIMEOUT on read client data. Client IP: ");

                sMsg.append(a_socket_ptr->remote_endpoint().address().to_string());

                throw MyException(sMsg);
        }

        // now we know there's something to read, so read
        boost::system::error_code error;
        size_t iBytesRead = a_socket_ptr->read_some(boost::asio::buffer(myVector), error);

        ...

おそらく、これはあなたの状況に役立つでしょう。

于 2011-04-20T18:43:43.547 に答える
9

Linux/BSD では、ソケットでの I/O 操作のタイムアウトは、オペレーティング システムによって直接サポートされています。このオプションは、 で有効にできますsetsocktopt()boost::asioそれを設定する方法を提供するのか、ソケットスクリプトを公開して直接設定できるようにするのかはわかりません.後者の場合は実際には移植性がありません.

完全を期すために、マニュアルページの説明を次に示します。

SO_RCVTIMEOSO_SNDTIMEO

          Specify the receiving or sending  timeouts  until  reporting  an
          error.  The argument is a struct timeval.  If an input or output
          function blocks for this period of time, and data has been  sent
          or  received,  the  return  value  of  that function will be the
          amount of data transferred; if no data has been transferred  and
          the  timeout has been reached then -1 is returned with errno set
          to EAGAIN or EWOULDBLOCK just as if the socket was specified  to
          be  non-blocking.   If  the timeout is set to zero (the default)
          then the operation  will  never  timeout.   Timeouts  only  have
          effect  for system calls that perform socket I/O (e.g., read(2),
          recvmsg(2), send(2), sendmsg(2)); timeouts have  no  effect  for
          select(2), poll(2), epoll_wait(2), etc.
于 2008-11-15T11:34:43.353 に答える
3

grepsedawk が言及したことに続きます。asio docoのTimeoutsセクションに、長時間実行されている非同期操作を一定期間後にキャンセルする方法を示すいくつかの例があります。ブースト Asio の例 . 非同期 TCP クライアントが最も役に立ちました。

幸せな非同期:)

于 2012-01-08T23:56:40.333 に答える
1

SO_RCVTIMEOの代わりに構造体をSO_SNDTIMEO取り込みます。したがって、@Pavel Verevkin のオプション 1. はan の代わりに a を取り込む必要があり、オプション 2. は単一の整数値のみを格納するため、クラスを実装する必要があります。timeval"sys/time.h"inttimevalintboost::asio::detail::socket_option::integer

于 2020-02-22T22:10:06.103 に答える
-2

*nix では、alarm() を使用して、ソケット呼び出しが EINTR で失敗するようにします。

于 2008-11-15T05:11:08.930 に答える