読み取り元の接続が開いているselectループがあり、各接続にステートマシンが接続されていて、ネットワークを介してやってくるものを解析して正しいことを行うと仮定します。したがって、接続の1つであるc
が準備ができていて、selectループがそれをステートマシンに渡してm
処理するとします。接続から10バイトを読み取りたいので、を使用しますreadpartial
。残念ながら、6バイトしか取得されていないため、m
6バイトを読み取ってブロックを解除します。次回ループが私たちに渡すとき、c
それはさらに11バイトあります。m
は、前回selectループから渡されたときの状態のままであり、c
さらに4バイトを読み取る必要があることを認識しているため、これらの4バイトを次のように読み取ります。readpartial(4)
は、現在バッファにあり、新しい状態に移行する10バイトを使用して、ある種の副作用操作を実行します。m
まだ接続を保持しているので、この時点でループのブロックを解除するか、新しい状態が指示する操作の実行を開始できます。これらの操作の1つは、を含むものである可能性がありますreadpartial
。この場合、正しいことは、readpartial
ブロックされないため、接続の処理を続行することです。しかし、アクションのシーケンスが次のようになっていると仮定します。6バイトを受信し、6バイトを読み取り、ブロックを解除し、4バイトを受信し、4バイトを読み取り、いくつかの処理を実行します。その場合、読むべきものは何も残っていないので、ステートマシンが呼び出すことを決定した場合readpartial
接続では、選択ループがブロックされますが、これは望ましくない状況です。この場合の正しいことは、ステートマシンがブロックを解除し、選択ループが再び発生するのを待つことです。
選択ループをブロックしたくない場合や、接続バッファーにバイトを残したくない場合に、この問題を解決するための正確で効率的な方法は何ですか?RubyのSocketとIOAPIを調べましたが、読むべきものがあるかどうかを教えてくれるメソッドが見つかりません。read_nonblock
は、1バイトを読み取ってから元に戻すことにより、ストリームが読み取り可能かどうかをテストするための潜在的な探索手段ですが、私のテストでは、期待どおりに動作しません。つまりchar = c.read_nonblock(1); c.ungetc(char); wire_data = c.read_partial(10)
、wire_data == char
接続バッファーchar
にバッファ。