2009-03-12 24 views
3

私はstdioを使用してファイル記述子をブロックする上でバッファリングされたIOが必要です。しかし、ファイル記述子を手動stdioに応じて非ブロックモードにすると、バッファリングは使用できなくなります。いくつかの研究の後、私はBIOがノンブロッキングIOのバッファリングに使用できることを確認します。ノンブロッキングIOをバッファリングするにはどうすればよいですか?

他の選択肢がありますか?

マルチ接続環境でスレッドを使用しないようにするには、これが必要です。

+0

あなたが使用している機能などのように、もう少し詳しく説明できますか? – dirkgently

+1

私はもう二度と、この質問は非常に難しいです。私はそれを理解していない、それは今言及されている方法です。 – unwind

+0

「BIOで参照してください」とは「ブロッキングIOで読み取り」を意味しますか?文脈はどういう意味ですか? – hhafez

答えて

15

あなたが話していることはReactor Patternだと思います。これは、スレッドなしで多くのネットワーク接続を処理するかなり標準的な方法であり、マルチプレイヤーゲームサーバーエンジンでは非常に一般的です。別の実装(Pythonで)はtwisted matrixです。

基本algorithは次のとおりです。

  • は、各ソケット用のソケットが読みする準備ができているチェック(選択し()、ポール()、または単に反復)
  • 各ソケット用バッファ
  • を持っています:
    • コールRECV()とRECVは0またはEWOULDBLOCK
    • 通話アプリケーションレベルDAとエラーが返されるまで、ソケットのバッファにコンテンツを蓄積しますRECV()は0を返すまで、あなたが開いている各ファイルディスクリプタのためのバッファを持つ構造体を作成することができ
+0

リアクターパターンの説明で私はlibowfatを見つけました。このスレッドからの私の必要性に最も適しています。感謝 –

3

私は質問が今編集されているのを見て、少なくとも以前よりも理解しやすいです。

とにかく、これは矛盾ではありませんか?

  • 少量のデータをすばやく読み込めるようにするために、通常は待ち時間のスループットを犠牲にしたいので、I/Oを非ブロックにします。
  • 遅延をあまり気にしませんが、スループットのためにトランザクションのレイテンシを使用してI/Oサブシステムを効率的に使用したいので、バッファリングします。

これらを同時に実行すると、矛盾しているように見えますが、想像するのは難しいです。

今後のセマンティクスについて教えてください。あなたがこれを行う場合:

int  fd; 
char buf[1024]; 
ssize_t got; 

fd = setup_non_blocking_io(...); 
got = read(fd, buf, sizeof buf); 

3バイトが利用可能な場合、どのような動作が期待できますか?ブロッキング/バッファリングされたI/Oは、要求をより多く満たすことができるまでブロックされる可能性があります。

もちろん、プロトコルが何らかのメッセージ構造を定義しているので、「このI/Oは不完全で、データがなくなるまで解析できません。そのレベルで自分自身をバッファリングし、完全なメッセージが受信されるまで上向きにデータを渡すことはできません。

+0

これにより、マルチ接続アプリケーションでのスレッドの使用を回避できます。 –

+1

これは矛盾ではありません。ノンブロッキングI/Oは、プログラムが他の作業(多くの場合、他の記述子を処理する必要がある)を必要とし、任意の記述子をブロックしたくない場合に最もよく使用されます。それは完全なバッファーを待つこととは多少異なるレイテンシです。 – dwc

0

バッファ

  • 明確なソケットのバッファの内容とソケットのTAハンドラ、その後、これらのバッファを蓄積またはあなたのバッファーで処理するのに十分なデータがあります。

    私はあなたの質問を正しく理解しているので、複数の接続(グローバルの場合)または同じデータを(ローカルの場合)書き込むだけで、非バッファリングで書き込みを行っているためバッファできません。

    いずれの場合でも、プログラムはデータが(ファイル記述子によって)どこから来ているのかを識別し、それに応じてバッファできる必要があります。

    スレッディングもオプションですが、多くの場合と同じように音が出ないほど怖いわけではありません。

  • 1

    プロトコルによっては、非ブロッキングネットワークノード(クライアントまたはサーバー)の読み取りをバッファリングする必要があります。

    通常、これらのバッファは、最後に処理されたバイトと最後に読み取られたバイト(処理されたオフセットと同じか大きい)の両方を記録する複数のインデックス(オフセット)を提供します。また、バッファの圧縮、透過的なバッファサイズ管理などのより豊富なセマンティクスも提供する必要があります。

    Javaでは、少なくとも非ブロッキングネットワークio(NIO)パッケージは、一連のデータ構造(ByteBuffer 、等)を含むことができる。

    Cのようなデータ構造が存在するか、自分でロールする必要があります。いったん入手したら、利用可能なデータを読み込み、バッファにオーバーフローなどの問題(メッセージフレーム境界をまたいでバイトを読み取るなど)を管理させ、マーカーオフセットを使用して処理したバイトをマークします。

    Androidが指摘しているように、開いている接続ごとに一致するバッファを作成する必要があります。

    0

    Ryan Dahl's evcom libraryこれはまさにあなたが望むものです。

    私は自分の仕事で使っています。ただし、(まだ、しかしすぐに)非同期DNS解決がないことに注意してください。 Ryanはそのためにudns by Michael Tokarevを提案します。私は今getaddrinfo()をブロックする代わりにudnsを採用しようとしています。

    関連する問題