6

複数のクライアントからの同時読み取り/書き込み操作をサポートする必要があるLinuxでサーバーを作成しています。選択機能を使用して、読み取り/書き込みの可用性を管理したいと思います。

私が理解していないのは、これです。ソケットに読み取り可能なデータが含まれるまで待ちたいとします。selectのドキュメントには、読み取り可能なデータができるまでブロックされ、読み取り関数はブロックされないと記載されています。

したがって、selectを使用していて、読み取り関数がブロックされないことがわかっている場合、ソケットを非ブロックに設定する必要があるのはなぜですか?

4

4 に答える 4

7

ソケットが準備完了として報告される場合がありますが、それを確認するまでに状態が変化します。

良い例の 1 つは、接続の受け入れです。新しい接続が到着すると、リッスンしているソケットが読み取りの準備ができていると報告されます。accept を呼び出すまでに、何かを送信する前、および を呼び出す前に、相手側によって接続が閉じられている可能性がありますaccept。もちろん、このケースの処理は OS に依存しacceptますが、新しい接続が確立されるまで単純にブロックされる可能性があります。これにより、アプリケーションが無期限に待機し、他のソケットの処理が妨げられます。リッスンしているソケットが非ブロック モードの場合、これは発生せず、EWOULDBLOCKまたはその他のエラーが発生しますが、acceptいずれにしてもブロックされません。

一部のカーネルには、UDP とselect. データグラムが到着すると、データグラムがselect読み取り準備完了としてマークされたソケットでウェイクアップします。データグラム チェックサムの検証は、ユーザー コードrecvfrom(または UDP データグラムを受信できる他の A​​PI) が呼び出されるまで延期されます。コードが呼び出さrecvfromれ、検証コードがチェックサムの不一致を検出すると、データグラムは単純に破棄recvfromされ、次のデータグラムが到着するまでブロックされます。この問題を修正するパッチの 1 つ (問題の説明と共に) は、ここにあります。

于 2012-10-07T21:12:58.950 に答える
4

他の人が言及したカーネルのバグ以外に、ポーリングループがある場合でも、非ブロッキングソケットを選択する別の理由は、高速で到着するデータでパフォーマンスを向上できることです。ブロッキングソケットが「読み取り可能」としてマークされている場合に何が起こるかを考えてください。到着したデータの量がわからないため、1回だけ安全に読み取ることができます。次に、イベントループに戻って、ソケットがまだ読み取り可能かどうかをポーラーに確認させる必要があります。これは、ソケットからの読み取りまたはソケットへの書き込みごとに、少なくとも2つのシステムコールを実行する必要があることを意味しますselect。読み取りが安全であることを通知するためと、読み取り/書き込み呼び出し自体です。

非ブロッキングソケットを使用するとselect、最初のソケットの後に不要な呼び出しをスキップできます。ソケットに読み取り可能のフラグが付けられてselectいる場合、データを返す限り、ソケットから読み取るオプションがあります。これにより、データの高速バーストの処理が高速化されます。

于 2012-10-08T08:04:14.400 に答える
2

利点の1つは、通常はブロックするソケットを読み取ろうとすると、代わりにEWOULDBLOCKが発生するため、プログラミングエラーが発生した場合にそれをキャッチできることです。ソケット以外のオブジェクトの場合、正確なAPIの動作が変わる可能性があります。http: //www.scottklement.com/rpg/socktut/nonblocking.htmlを参照してください。

于 2012-10-07T21:10:39.720 に答える
2

これは皮肉に聞こえるかもしれませんが、そうではありません。ブロックしないようにする一番の理由は、ブロックしないようにすることです。

考えてみてください。 select()読むべきものがあると言いますが、どれくらいかわかりません。2 バイトかもしれないし、2,000 かもしれません。ほとんどの場合、 に戻る前にそこにあるデータを排出する方が効率的selectです。そのため、読むためにwhileループに入ります

while (1)
{
    n = read(sock, buffer, 200);
    //check return code, etc
}

読み取るものが残っていない場合、最後の読み取りで何が起こりますか? ソケットがノンブロッキングでない場合は、ブロックするため、(少なくとも部分的に) select().

于 2012-10-08T00:30:49.240 に答える