2008-09-15 5 views
14

Net.Sockets.TcpListenerを使用する場合、着信接続(.AcceptSocket)を別々のスレッドで処理する最善の方法は何ですか?tcplistenerの着信接続を.NETのスレッドに分散する方法は?

考えられるのは、新しい着信接続が受け入れられたときに新しいスレッドを開始することです。その後、tcplistenerはそれ以降の着信接続(新しい着信接続ごとに新しいスレッドが作成される)で使用できるようになります。接続を開始したクライアントとのすべての通信と終了はスレッドで処理されます。

例C#のVB.NETコードが評価されています。

答えて

15

コード:

class Server 
{ 
    private AutoResetEvent connectionWaitHandle = new AutoResetEvent(false); 

    public void Start() 
    { 
    TcpListener listener = new TcpListener(IPAddress.Any, 5555); 
    listener.Start(); 

    while(true) 
    { 
     IAsyncResult result = listener.BeginAcceptTcpClient(HandleAsyncConnection, listener); 
     connectionWaitHandle.WaitOne(); // Wait until a client has begun handling an event 
     connectionWaitHandle.Reset(); // Reset wait handle or the loop goes as fast as it can (after first request) 
    } 
    } 


    private void HandleAsyncConnection(IAsyncResult result) 
    { 
    TcpListener listener = (TcpListener)result.AsyncState; 
    TcpClient client = listener.EndAcceptTcpClient(result); 
    connectionWaitHandle.Set(); //Inform the main thread this connection is now handled 

    //... Use your TcpClient here 

    client.Close(); 
    } 
} 
+0

ソースコードをありがとう、私はこれのようにコーディングされます。 新しいスレッドは高価になる可能性がありますが、5〜6同時接続の受信接続を超えて拡張することはできません。 –

+1

リスナーとtcpListenerが混乱していると思います。 これを見つけた:http://msdn.microsoft.com/en-us/library/system.net.sockets.tcplistener.beginaccepttcpclient.aspx私はここに賛成します。 –

+0

現在のコードはパフォーマンスのコンテキストで非常に危険です。私はそれを編集します... – Beygi

0

スレッドプールを使用すると、毎回新しいスレッドを開始する必要はありません(これはちょっと高価です)。私は、クライアントが接続を閉じることができないため、より忙しい接続のために無期限に待つこともありません。どのように毎回同じスレッドにクライアントをルーティングする予定ですか?

申し訳ありませんが、サンプルがありません。

3

これは、.NETの他の非同期操作と同じ方法で行うと考えています。この場合、BeginXxxバージョンのメソッド(この場合はBeginAcceptSocket)を呼び出します。コールバックはスレッドプール上で実行されます。

一般にプールされたスレッドは、接続ごとのスレッドよりもはるかに優れています。数十回の接続を超えると、システムは実際の作業を行うよりもスレッド間の切り替えがはるかに難しくなります。さらに、各スレッドは、(32ビットシステム上で)2GBの仮想アドレス空間で見つかるはずの(通常はリンクフラグに依存しますが)通常はサイズが1MBの独自のスタックを持っています。これは実際には1000スレッド未満に制限されます。

.NETのスレッドプールで現在使用されているかどうかはわかりませんが、スケーラブルなI/Oを支援するI/O完了ポートと呼ばれるカーネルオブジェクトがWindowsにあります。スレッドをこのオブジェクトに関連付けることができ、I/O要求(着信接続の受け入れを含む)を関連付けることができます。 I/Oが完了すると(たとえば、接続が到着すると)、Windowsは待機中のスレッドを解放しますが、現在実行可能なスレッドの数が他の理由でブロックされていない場合にのみ完了ポートのスケーラビリティ制限が小さくなります。通常、これをコア数の小さな倍数に設定します。

2

私は、異なるアプローチを提案したいと思います。 私の提案では、2つのスレッドしか使用しません。 * 1つのスレッドが接続をチェックしています。 *新しい接続が開かれると、この情報は、現在開いているすべての接続を保持する共有データ構造に書き込まれます。 * 2番目のスレッドは、そのデータ構造を列挙し、開いている接続ごとにデータを受信し、返信を送信します。

この解決策はスレッド単位でスケーラビリティがあり、実装した方がパフォーマンスが向上し、開かれた接続ごとに新しいスレッドを開く必要があります。私はこのようなルックスを使用してきた

+0

これは本当にすぐにそれぞれの着信接続にお答えしたいと思いますが、私は、覚えています。提案していただきありがとうございます。 –

+0

こんにちは! @エラーヘルパー、あなたの提案は良いのように見えます。どのように効率戦略を実装するには?共有することができますか、コードスニペットはありますか? – bashkan

関連する問題