2009-08-10 56 views
2

私たちはTCP/IPソケットを介して他のシステムと通信する必要のあるC#アプリケーションを作成しています。毎秒約1〜2回の受信トランザクションを受信すると予想され、各メッセージのサイズは平均約10k(テキストと1画像)です。TCPListenerクラスを使用したシングルスレッドまたはマルチスレッド?

これで、いくつかの処理が行われます(いくつかの変数に応じて100ミリ秒から3秒の間にかかることがあります)。その後、約1kの応答を返します。

私が見た例では、いくつかはマルチスレッドです。このアプリケーションでは、シングルまたはマルチスレッド化する方が良いでしょうか?マルチスレッドが推奨されている場合は、おおよそ異なるスレッドが何をしますか?

答えて

3

複数の接続が必要な場合は、複数のスレッドが必要です。各スレッドには、個別に処理する必要がある特定のクライアントのストリームが与えられます。

Silverlight policy serverは、マルチスレッドサーバーアプリケーションの素晴らしい最初の例だと思います。ただし、TcpListenerではなくSocketクラスを使用します。

+0

同じクライアントからの同じポート上の多くの接続が「複数の接続」または1つの接続を構成したとしますか? – alchemical

+0

それでも複数の接続と見なされます。 –

5

は(C#に固有ではない)

両方向(極端な性能が決定的な要因ではなかった)、それを行ったが、私ははるかに1スレッドあたりの接続アプローチを好みます。

リスナースレッド
このスレッドの仕事は、着信接続用のソケットに耳を傾け、それらを受け入れて、そして(それに接続されたソケットを与えて)新しい接続のスレッドを生成することです。

接続スレッド
これらのスレッド(接続ごとに1つ)に接続されたソケットとの通信のすべてを取り扱います。同期している場合は、リクエストの処理を処理することもできます(特定のアプリのために調べる必要があります)。

接続が切断されると、このスレッドも終了します。

管理スレッド
クリーンアップ、または定期的なメンテナンスが、これらは独自のスレッドですべて実行することができ、行っ必要がある場合。

ロックをかけてください(明らかに): どのくらいのデータを共有する必要がありますか?アクセス時にすべてのリソースが正しくロックされていること、デッドロックや競合状態がないことを確認してください。しかし、それは "一般的なスレッド"のトピックです。

+3

要求ごとに新しいスレッドを生成する代わりに、スレッドプールを使用することを検討してください。新しいスレッドの作成はコストがかかり、DOS攻撃の可能性が高くなります。 – CsTamas

+0

いくつかの共有リソースがあります:データベース接続オブジェクト、ロギングオブジェクトなどこれらは一般にスレッドセーフなシングルトンですが、各スレッドに独自のインスタンスを与えることもできます。 – alchemical

+0

極端なパフォーマンスが主な考慮点 - 何が複数のスレッドを優先させましたか? – alchemical

2

私はソケットを受け入れ、非同期呼び出しを使用します。複数の接続を受け入れ、すべての接続に対してスレッドを作成しないようにすることができます。

基本的リスナー

ソケットソケット= tcpListener.AcceptSocket(持つソケットを作成します)。

と、データの受信を開始するSocket.BeginReceive。

0

「接続」という言葉の意味を定義することが重要だと思います。'

トランザクションが送信されるたびに、他のシステムがTcpListenerへの新しい接続を作成する場合、これは複数の接続とみなされ、これらの着信接続要求を処理する専用のスレッドを持つことは理にかなっています。このような場合は、これ以外のすべてを無視し、gahooaの提案ソリューションを使用してください。

一方、他のシステムが単純に接続を確立し、その同じ接続を介してすべてのトランザクションを送信すると、(接続が1つしかないため)別のスレッドで接続要求を処理することは実際にはありません。これが当てはまる場合は、着信要求を一度受け入れ、ソケットを非同期で読み取ることをお勧めします(データのソケットをポーリングするのではなく)。あなたが完全なトランザクションを受け取るたびに、それをトランザクション処理スレッドに「壁越しに」スローします。処理が完了し、 "答え"が計算されると、結果を他のシステムに返す応答スレッドに "壁越しに"スローします。

  1. メインスレッド
  2. 読むスレッド
  3. 処理スレッド
  4. 書き込みスレッド

は、メインスレッドがTcpListenerを作成し、接続するまで待機:このシナリオでは、基本的に4件のスレッドがあります確立されています。その時点で、非同期読み取りを開始し、プログラムが終了するまで待機します(ManualResetEvent.WaitOne())。

読み取りスレッドは、NetworkStreamからの読み取りを処理する非同期スレッドです。

処理スレッドは、読み取りスレッドからトランザクションを受け取り、必要な処理を行います。

書き込みスレッドは、処理スレッドによって生成された応答をすべて取り出し、それらをNetworkStreamに書き込みます。

このlinkによれば、読み取りと書き込みが別のスレッドで行われている限り、同じNetworkStreamからの読み取りと書き込みを同期させる必要はありません。ジェネリックリストまたはキューを使用して、スレッド間でデータを移動できます。私はRead-to-Processingデータ用とProcessing-to-Writeデータ用に作成します。 SyncRootプロパティを使ってアクセスを同期させてください。

関連する問題