2013-10-03 17 views
11

select()poll()またはepoll()を比較した記事をいくつか見てきましたが、複数のソケットを使用したselect()の実際の使用方法を議論している多くのガイドがあります。ソケットselect()とnon-block recv

しかし、私が見つけることができないのは、ノンブロッキングrecv()との比較であり、select()なしの呼び出しです。 1ソケットの読み込みと1ソケットの書き込みだけがある場合は、select()呼び出しを使用する正当な理由はありますか? recv()メソッドは、利用可能なデータがないときにブロックしてエラー(WSAEWOULDBLOCK)を返さないように設定することができます。他のソケットがない場合はselect()と呼ぶのはなぜですか?ノンブロッキングrecv()の呼び出しは非常に遅いですか?

+0

おそらく実装の詳細すべてです。それを試しましたか? –

+0

連続して読み込むデータがないときにはどうしますか?永遠にループ?またはselectまたはpollまたはepollを使用しますか?ブロッキングまたはノンブロッキングに関係なく、何らかの形でデータを待つ必要があります。 – goji

+0

はい、@トロイは言ったように、あなたはアクティブ待ちを実装するでしょう - 何も読んでいないときは、プロセッサの慈悲を意味しません。 – zoska

答えて

9

あなたはCPU時間を無限にポーリングするときにソケット上のデータを待つための何らかの手段なしに、recvへの非ブロッキング呼び出しを望んでいません。

検査するソケットが他になく、同じスレッドで何も実行しない場合は、読み込みをブロックする呼び出しが最も効率的なソリューションになる可能性があります。このような状況では、この効率を考慮することは早すぎる最適化に似ています。

このような考慮事項は、ソケット数が増えるにつれて重要になりがちです。

ノンブロッキングコールは、単一のスレッド上で複数のソケットを処理するコンテキストでのみ高速になります。

+1

あなたの回答と、以下の回答から、recv()がCPUをより多く使用していることがわかりました。これは、ループ内のselect()が実際にスレッドを中断したと思わせます。これは私が不思議の国の社会義線の違いかもしれません。 また、これが当てはまる場合、私はそれが期間中だけ中断することが疑わしくなります。これは選択をブロッキングコールに変えますか? これを学ぶには、最大速度で処理するために2つのソケットスレッド(1つは入力、1つは出力)が必要ですが、出力は新しいデータがキューから利用可能になったときに問題になります? –

+0

'select()'を呼び出す前に、その構造体(bitsets)を設定します。書き込み可能な状態にバッファリングされたデータを持っている場合は、書き込みビットセットに出力ソケットを設定すると、入力ソケットは常に読み取りビットセットに設定されます。これは非常に典型的な選択の使用法であり、Googleには多くの例があります。 – goji

+1

この本は、聖書のイモです:http://www.amazon.com/UNIX-Network-Programming-Networking-Sockets/dp/013490012X – goji

3

利用可能なデータがなく、ノンブロッキングIOを使用している場合、recv()はすぐに戻ります。 それでは、プログラムは何をすべきですか?データが入手可能になるまで、recv()をループで呼び出す必要があります。これは、CPUをまったく理由なく使用します。

recv()でスピニングし、そのようにCPUを焼くことは非常に望ましくありません。むしろ、データが利用可能になり、目が覚めるまでプロセスが待つようにしたいのです。それはselect()/poll()と同様です。

そして、CPUを燃やさないためにループ内のsleep()も良い解決策ではありません。データが利用可能になるとすぐにプログラムがデータを処理できないため、処理時間が長くなります。

5

select()と友人は、1つのソケットの速度が遅くても、別のサービスを提供できる速度を妨げないようにワークフローを設計できるようにします。受信ソケットからデータが速く到着し、できるだけ早く受け取り、メモリバッファに格納したいとします。しかし、送信ソケットは遅いです。 OSの送信バッファをいっぱいにして、send()があなたにEWOULDBLOCKを与えたら、select()を発行してソケットの送受信を待つことができます。 select()は、受信ソケットの新しいデータが到着した場合や、一部のバッファが解放された場合に送信ソケットにデータを書き込むことができます。

もちろん、select()のより現実的な使用例は、読み書きや書き込みを行うソケットが複数ある場合や、2つのソケット間で両方向にデータを渡す必要がある場合です。

実際、は、ソケット上の次の読み取りまたは書き込み操作が成功するとわかるため、selectが許可すると読み取りと書き込みを試みるだけで、プログラムはほとんど動作しませんソケットを非ブロックにしてください!select()がソケットを「準備完了」として報告したにもかかわらず、次の操作がまだブロックされる場合があるため、それでもやり方は賢明ではありません。

一方、reason explained by @Troyのために、ソケットを非ブロック化して使用しないようにしてください。select()はほとんどお勧めできません。

関連する問題