Working with TCP Sockets 読書メモ 第7章 ノンブロッキングIO

目次


ノンブロッキングIO

  • ノンブロッキングIOは、コネクションの多重化によって実現できる

ノンブロッキングな読み込み

  • readを使うと、EOFを受け取るまでブロックする
  • readpartialを使えば今読めるデータだけを取得できるが、データが送られないとブロックする
  • 絶対に ブロックしないようにするには、read_nonblockを使用する

  • データが無い場合、Errno::EAGAINの例外が発生する
  • Errno::EAGAINが発生したらretryしている
    • プロダクションで推奨される実装ではないので注意
  • retryの実行を制御する例は以下

  • IO.selectを使うと、connectionから読み込みが可能になるまでブロックする
  • 読み込みが可能になった時点でretryしている
  • この実装では、読み込み可能までブロックするので、readを使うのと変わらない!

読み込みはいつブロックするのか?

  • read_nonblockメソッドはRubyの内部バッファをチェックして保留中のデータがないか確認する
    • select(2)を使って利用可能なデータを確認する
  • 利用可能なデータがある場合はデータが返り、利用可能なデータがない場合はブロックする

ノンブロッキングな書き込み

  • write_nonblockによってノンブロッキングな書き込みを実装できる

  • write_nonblockは、大量のデータ送信等でブロックするような状態に陥った場合、全てのデータを送信せずに送信済みのバイト数を返す
    • 残りのデータは改めて送信する必要がある
  • write_nonblockの挙動はwrite(2)と同じ
  • Rubyのwriteは何度もwrite(2)を呼んで全てのデータを書き込む
  • write_nonblockの制御にもIO.selectが利用できる

  • IO.selectの第2引数にソケット配列を渡すと、書き込み可能になるまでブロックする
  • write_nonblockとpayloadのスライスを繰り返して、全てのデータを送信している

書き込みはいつブロックするのか?

  • write(2)がブロックする可能性があるのは以下の2つの状況
  1. TCPコネクションの受信側に到達するのに時間がかかるとき
  2. 受信側が処理可能なデータ量の限界を超えているとき

ノンブロッキングなaccept

  • 通常のacceptは、キューにコネクションが1つもないとブロックする
  • accept_nonblockは、キューにコネクションがないとErrno::EAGAINを発生させる

ノンブロッキングなconnect

  • connect_nonblockの挙動は、他のxxx_nonblockとは異なる
  • xxx_nonblockは正常に処理を行うか、例外を投げるかのいずれか
  • connect_nonblockは、処理を行い、 かつ 、例外を投げることがある
  • リモートホストと即時に接続ができない場合、バックグラウンドで接続を試みつつErrno::EINPROGRESSを発生させる
  • 詳細なサンプルは次章

“Working with TCP Sockets 読書メモ 第7章 ノンブロッキングIO” への 1 件のフィードバック

コメントを残す