6

Linux/Unix ソケットのチュートリアルについてインターネットで見たすべてのチュートリアルと例では、サーバー側のコードには常にクライアント接続を毎回チェックする無限ループが含まれています。例:

http://www.thegeekstuff.com/2011/12/c-socket-programming/

http://tldp.org/LDP/LG/issue74/tougher.html#3.2

無限ループを含まないようにサーバー側のコードを構造化する、またはシステム リソースの消費量が少なくなるように無限ループをコーディングする、より効率的な方法はありますか?

4

7 に答える 7

6

これらの例の無限ループはすでに効率的です。への呼び出しaccept()はブロッキング呼び出しです。この関数は、クライアントがサーバーに接続するまで戻りません。関数を呼び出したスレッドのコード実行accept()は停止され、処理能力はまったく消費されません。

ミューテックス/ロック/セマフォaccept()の呼び出しまたは待機のように考えてください。join()

もちろん、着信接続を処理する方法は他にもたくさんありますが、それらの他の方法は のブロッキングの性質を扱いますaccept()。この関数はキャンセルするのが難しいため、着信接続を待機している間にサーバーが他のアクションを実行できるようにする非ブロッキングの代替手段が存在します。そのような代替手段の 1 つは、 を使用することselect()です。他の代替手段は、オペレーティングシステムによって処理されるコールバック関数、イベント、またはその他の非同期メカニズムを介して接続を通知するための低レベルのオペレーティングシステム呼び出しを含むため、移植性が低くなります...

于 2012-07-27T11:57:27.733 に答える
1

利用可能な手法の概要は次のとおりです-C10K問題

于 2012-07-27T12:08:16.620 に答える
1

無限ループはサーバーの実行状態を維持するためにあります。そのため、クライアント接続が受け入れられると、サーバーはすぐに終了せず、代わりに別のクライアント接続のリッスンに戻ります。

listen() 呼び出しはブロッキング呼び出しです。つまり、データを受信するまで待機します。これは非常に効率的な方法であり、リッスンしているスレッドを起動するイベント (またはハードウェア割り込み) をトリガーするオペレーティング システムのネットワーク ドライバーを利用することで、(もちろん接続が確立されるまでは) ゼロのシステム リソースを使用します。

于 2012-07-27T11:57:59.470 に答える
1

C++ の場合はboost.asioを調べることができます。また、非同期 I/O関数などを調べることもできます。もありSIGIOます。

もちろん、これらの非同期メソッドを使用している場合でも、メイン プログラムはループに入る必要があります。そうしないと、プログラムが終了します。

于 2012-07-27T11:56:24.120 に答える
0

クライアント サーバー プログラミングを記述する際のベスト プラクティスに従う必要があります。現時点でお勧めできる最良のガイドはThe C10K Problemです。この場合、従わなければならない特定の事項があります。select または poll または epoll を使用できます。それぞれに長所と短所があります。

最新のカーネル バージョンを使用してコードを実行している場合は、epoll を使用することをお勧めします。epollを理解するためのサンプル プログラムを表示するには、ここをクリックします。

select、poll、epoll を使用している場合は、システム時間を消費してサーバーが無限ループに陥らないように、イベント/トリガーを取得するまでブロックされます。

私の個人的な経験では、80k ACTIVE 接続を持つサーバー マシンのしきい値が、選択とポーリングを比較すると非常に低いことがわかったため、epoll がさらに進むための最良の方法であると感じています。私のサーバーマシンの負荷平均は、80kのアクティブな接続でわずか3.2でした:)

ポーリングでテストしたところ、アクティブなクライアント接続が 30,000 に達すると、サーバーの負荷平均が 7.8 に達したことがわかりました :(.

于 2012-08-09T08:48:59.823 に答える
0

既に投稿されているものに加えて、デバッガーで何が起こっているかを確認するのはかなり簡単です。accept() 行を実行するまでシングルステップスルーできます。実行すると、「シングルステップ」ハイライトが消え、アプリが実行されます - 次の行には到達しません。次の行にブレークポイントを置くと、クライアントが接続するまで起動しません。

于 2012-07-27T14:20:21.193 に答える
0

おそらく無限の接続をリッスンするサーバーを実装している場合、ある種の無限ループを回避する方法はありません。ソケットが非ブロッキングとしてマークされていない場合、 への呼び出しaccept()は新しい接続が到着するまでブロックされるため、通常、これはまったく問題になりません。このブロックにより、システム リソースが浪費されることはありません。

イベントベースのシステムのように提供する他のライブラリは、最終的に上記の方法で実装されます。

于 2012-07-27T11:58:14.900 に答える