2011-02-07 4 views
4

私は、クライアントソケットのセットを監視するこのスレッドを自分のアプリケーションに持っています。私はselect()を使用して、クライアントがリクエストを行うまでブロックし、スレッドを増やすことなく効率的に処理できるようにします。ファイルへの書き込みをせずにselect()を実行します。desc?

クライアントのリストに新しいクライアントを追加すると、実際に新しいソケットをリッスンされたソケットに追加するために、タイムアウトがselect()(10秒に設定)まで待たなければなりません。

select()の前に、の前にクライアントをすぐに聴くことができるようにしたいと思います。

私はすでにそれを解決しています:私はいつも聞いたソケットリストに含まれているダミーのソケットペアを作成して、select()のクラックを書くようにしていますが、もっと良い解決方法があると思っています。

編集:私が使用したglibcが古すぎるので 私はeventfd()にはアクセスできません(と私はそれを更新する平均を持っていません)。ですから、私はfifoやソケットを使わなければならないかもしれません。

ご存知ですか?

ありがとうございます!

+0

あなたは 'pthread_kill'などでスレッドを終了させて​​から再起動することができます... – jswolf19

+0

それは...残念でしょうか? – Gui13

答えて

7

選択ループを起動する通常の方法は、pipe() fdペアの読み出し側を選択の監視セットに追加することです。 selectループを起動する必要があるときは、ファイルディスクリプタの書き込み側にダミーデータを書き込んでください。

pipe()ではなく、eventfd()を使用することをお勧めします(ポータブルではありませんが)。

また、リスンソケットを別のスレッドに渡す代わりに、選択ループで処理することもできます。これは、新しいクライアントが来たときに暗黙的に選択ループを起動します。

+0

'eventfd()'は私が必要としていたものです!私はLinuxに焦点を当てているので、完璧です。ありがとう! – Gui13

+0

ここでは大丈夫です:私はeventfd()をサポートする最後のGLibcを持っていないので、fifoやソケットを使ってフォールバックする必要があります。 fifoでうまくいかないのは、open()/ close()と私が避けたいファイルシステムのすべてです。それを防ぐための迅速な方法はありますか? – Gui13

+0

'fifo()'のマンページを読んだことがありますか?ファイルシステムにアクセスする必要はありません。ファイルディスクリプタを用意するだけです。注意すべき点の1つは、他のプログラムを実行する場合に 'fcntl()'を使ってFD_CLOEXECを設定することです。 – bdonlan

0

EINTRを強制的にselect()から呼び出すことはできますが、マルチスレッドプログラムのシグナル処理は黒い魔法です。

+0

マルチスレッドプログラムのシグナルは、選択ループを起動するだけですか?人間が必要とするより複雑な方法...地獄では、人々はシグナルハンドラからのfifo-wakeupパターンを使ってシグナルを正確に処理しません。逆にしないでください。 – bdonlan

+0

これはまさに私が言っていたことです:あなたはすることができますが、そうすべきではありません。 – blaze

3

FDセットにリスナーソケットを含めることによって、着信接続を待つために同じselect()コールを使用できます。この方法では、接続が待機中であることを示すときに、ブロックせずに接続を受け入れ、新しいファイル記述子をセットに追加することができます。

+0

これは私が最初に考えたことですが、主なリスニングソケットは、アプリケーションの別の部分で別のselect()で既に使用されています(リスニングソケットはクライアントを追加する以外の目的に使用できます)。私の場合、解決策は実用的ではありません。 – Gui13

0

WSAEventSelectを使用すると、WindowsソケットをHEVENTにリンクしてから、WaitForMultipleObjectsを使用して別のディスクリプタでソケットHEVENTにリンクすることができます。

関連する問題