4

それは本当に質問ではありません。私はいくつかのガイドラインを探しているだけです:)私は現在、可能な限り少ない数のスレッドを使用する必要がある抽象tcpサーバーを作成しています。

現在、この方法で動作しています。リスニングを行うスレッドといくつかのワーカー スレッドがあります。リスナー スレッドはただ座ってクライアントが接続するのを待ちます。サーバー インスタンスごとに 1 つのリスナー スレッドがあると予想されます。ワーカー スレッドは、クライアント ソケットですべての読み取り/書き込み/処理ジョブを実行しています。

だから私の問題は、効率的なワーカープロセスを構築することです。そして、私はまだ本当に解決できない問題に直面しました。ワーカーコードは次のようなものです(コードは、私が問題を抱えている場所を示すためだけに非常に単純です):

List<Socket> readSockets = new List<Socket>();
List<Socket> writeSockets = new List<Socket>();
List<Socket> errorSockets = new List<Socket>();

while( true ){
    Socket.Select( readSockets, writeSockets, errorSockets, 10 );

    foreach( readSocket in readSockets ){
        // do reading here
    }

    foreach( writeSocket in writeSockets ){
        // do writing here
    }

    // POINT2 and here's the problem i will describe below 
}

whileループが何度も繰り返されるため、CPU使用率が100%であっても問題なく動作します。クライアントがsend->receive->disconnectルーチンを実行している場合、それほど苦痛ではありませんが、send->を実行して生き続けようとするとreceive->send->receive を繰り返すと、実際にすべての CPU が消費されます。だから私の最初のアイデアはそこにスリープを置くことでした.すべてのソケットにデータが送信されているかどうかを確認し、Thread.Sleep を POINT2 に 10 ミリ秒だけ入れますが、この 10 ミリ秒後に、次に受信したいときにその 10 ミリ秒の大きな遅延が発生しますクライアント ソケットからのコマンド。

多分それは単に貧弱なアーキテクチャですか?プロセッサーの使用率が 100% にならないようにするにはどうすればよいでしょうか。また、サーバーがクライアント ソケットに表示される何かにできるだけ早く反応するようにするにはどうすればよいでしょうか? たぶん誰かがノンブロッキングサーバーとそれが維持すべきアーキテクチャの良い例を指摘できますか?

4

4 に答える 4

4

最初にTcpListenerクラスを見てください。ブロックしない BeginAccept メソッドがあり、誰かが接続したときに関数の 1 つを呼び出します。

SocketクラスとそのBeginメソッドも見てください。これらは同じように機能します。特定のイベントが発生するたびに関数の 1 つ (a callback function) が呼び出され、そのイベントを処理できるようになります。すべてのBeginメソッドは非同期であるため、ブロックされず、CPU を 100% 使用することもありません。基本的に、読み取りにはBeginReceiveが必要で、書き込みにはBeginSendが必要だと思います。

これらのメソッドと非同期ソケットのチュートリアルを検索すると、Google でさらに多くの情報を見つけることができます。たとえば、この方法で TCP クライアントを実装する方法を次に示しますサーバーでも基本的に同じように機能します。

この方法では、無限ループは必要ありません。すべてイベント駆動型です。

于 2010-04-24T21:28:00.837 に答える
1

ピアツーピアアプリケーションまたはクライアントサーバーアプリケーションを作成していますか?ソケットに入れるデータの量も考慮する必要があります。

非同期のBeginSendとBeginReceiveがその方法です。イベントを実装する必要がありますが、正しく設定すれば高速です。

おそらく、送信と受信のタイムアウトも高く設定したくないでしょうが、一定時間後に何も受信されない場合にブロックから出てそこで処理できるように、タイムアウトが必要です。

于 2010-04-28T06:58:59.403 に答える
1

Microsoft には、すばらしい非同期 TCP サーバーの例があります。頭を包み込むには少し時間がかかります。この例に基づいて、自分のプログラム用の基本的な TCP フレームワークを作成できるようになるまで、数時間かかりました。

http://msdn.microsoft.com/en-us/library/fx6588te.aspx

プログラムのロジックは、次のようになります。listener.BeginAccept を呼び出して allDone.WaitOne をブロックするスレッドが 1 つあります。BeginAccept は、スレッドプールにオフロードされ、OS によって処理される非同期呼び出しです。新しい接続が入ると、OS は BeginAccept から渡されたコールバック メソッドを呼び出します。そのメソッドは、allDone を反転して、メインのリッスン スレッドに、もう一度リッスンできることを知らせます。コールバック メソッドは単なる一時的なメソッドであり、引き続き別の非同期呼び出しを呼び出してデータを受信します。

提供されるコールバック メソッド ReadCallback は、非同期呼び出しの主要な作業「ループ」(事実上再帰的な非同期呼び出し) です。各メソッド呼び出しが実際に終了するため、「ループ」という用語を大まかに使用しますが、次の非同期メソッドを呼び出す前ではありません。事実上、互いに呼び出している非同期呼び出しがたくさんあり、「状態」オブジェクトを渡します。このオブジェクトはあなた自身のオブジェクトであり、あなたはそれで好きなことをすることができます。

すべてのコールバック メソッドは、OS がメソッドを呼び出したときに返されるものを 2 つだけ取得します。

1) 接続を表すソケット オブジェクト

2) ロジックに使用する状態オブジェクト

状態オブジェクトとソケット オブジェクトを使用すると、「接続」を非同期で効果的に処理できます。OSはこれが非常に得意です。

また、メインループは接続が来るのを待ってブロックし、非同期呼び出しを介してそれらの接続をスレッドプールにオフロードするため、ほとんどの場合アイドル状態のままです。ソケットのスレッド プールは、完了ポートを介して OS によって処理されるため、データが入るまで実際の作業は行われません。CPU はほとんど使用されず、スレッド プールを介して効果的にスレッド化されます。

PS私が理解していることから、データの移動を処理するだけで、これらのメソッドで難しい作業をしたくありません。スレッド プールはネットワーク IO のプールであり、他のプログラムによって共有されるため、ソケット スレッド プールが行き詰まらないように、threads/tasks/async を介してハードワークをオフロードする必要があります。

PPS「リスナー」を破棄する以外に、リスニング接続を閉じる方法が見つかりませんでした。beginListen の非同期呼び出しが呼び出されるため、そのメソッドは接続が確立されるまで戻りません。つまり、戻るまで停止するように指示することはできません。これについては、MSDN に質問を投稿しようと思います。良い反応があればリンクします。

于 2011-10-04T14:04:16.433 に答える
0

あなたのコードはタイムアウト値を除いてすべて問題ありません。これを 10 マイクロ秒 (10*10^-6) に設定すると、 while ルーチンが頻繁に繰り返されます。適切な値 (たとえば 10 秒) を設定する必要があり、コードが 100% の CPU を消費することはありません。

List<Socket> readSockets = new List<Socket>();
List<Socket> writeSockets = new List<Socket>();
List<Socket> errorSockets = new List<Socket>();

while( true ){
    Socket.Select( readSockets, writeSockets, errorSockets, 10*1000*1000 );

    foreach( readSocket in readSockets ){
        // do reading here
    }

    foreach( writeSocket in writeSockets ){
        // do writing here
    }

    // POINT2 and here's the problem i will describe below 
}
于 2015-04-23T12:06:47.080 に答える