2010-12-29 5 views
1

私はシンプルなtcpサーバを作成しました。簡単なtcpサーバをテストすると10060(接続タイムアウト)になる

ストレステストに切り替えると問題が発生します。私たちのサーバーは多くの同時オープンソケットを処理するため、これを確認するためのストレステストが作成されています。 残念ながら、サーバが窒息しているようで、同時にオープンしているソケットの数が100個程度のときに、新しい接続要求にタイムリーに応答できません。

すでに少数のサーバを試しましたが、 。

サーバー:この記事のサンプルのようなもの(すべて同じ動作を生成)

How to write a scalable Tcp/Ip based server

ここで私たちが使用しているコードであることができます - クライアントが接続したときに - サーバーがしますだけでは、ソケットを生かし続けるためにハングアップします。

enter code here 

パブリッククラスサーバー

{ 
    private static readonly TcpListener listener = new TcpListener(IPAddress.Any, 2060); 

    public Server() 
    { 
     listener.Start(); 
     Console.WriteLine("Started."); 

     while (true) 
     { 
      Console.WriteLine("Waiting for connection..."); 
      var client = listener.AcceptTcpClient(); 
      Console.WriteLine("Connected!"); 
      // each connection has its own thread 
      new Thread(ServeData).Start(client); 
     } 
    } 

    private static void ServeData(object clientSocket) 
    { 
     Console.WriteLine("Started thread " + Thread.CurrentThread.ManagedThreadId); 

     var rnd = new Random(); 
     try 
     { 
      var client = (TcpClient)clientSocket; 
      var stream = client.GetStream(); 
      byte[] arr = new byte[1024]; 
      stream.Read(arr, 0, 1024); 
      Thread.Sleep(int.MaxValue); 

     } 
     catch (SocketException e) 
     { 
      Console.WriteLine("Socket exception in thread {0}: {1}", Thread.CurrentThread.ManagedThreadId, e); 
     } 
    } 
} 

ストレステストのクライアントは単純なTCPクライアント、そのループとオープンsoketsで、他の

class Program 
    { 
     static List<Socket> sockets; 
     static private void go(){ 
      Socket newsock = new Socket(AddressFamily.InterNetwork, 
            SocketType.Stream, ProtocolType.Tcp); 
      IPEndPoint iep = new IPEndPoint(IPAddress.Parse("11.11.11.11"), 2060); 
      try 
      { 
       newsock.Connect(iep); 
      } 
      catch (SocketException ex) 
      { 
       Console.WriteLine(ex.Message); 
      } 
      lock (sockets) 
      { 
       sockets.Add(newsock); 
      } 

     } 
     static void Main(string[] args) 
     { 
      sockets = new List<Socket>(); 
      //int start = 1;// Int32.Parse(Console.ReadLine()); 
      for (int i = 1; i < 1000; i++) 
      { 
       go(); 
       Thread.Sleep(200); 
      } 
      Console.WriteLine("press a key"); 
      Console.ReadKey(); 




     } 
    } 
} 

後の1は、簡単な方法がありますこの動作を説明するには?おそらくC + +の実装は、TCPサーバーは、より良い結果を生成する場合?実際にはクライアント側の問題でしょうか?

コメントは歓迎されます!

オフェル

+1

あなたはどのOSでテストしていますか?すべての接続に対して新しいスレッドを作成するべきではありません。一般的なスケーラビリティのために非同期インターフェイスを使用することを検討する必要があります。BeginAccept、BeginReceiveなどを参照してください。 –

+0

win 7.私は非同期のアプローチが望ましいということを認識しています。ただし、上記の動作は、私が試したサーバー実装(コールバックを含む)で発生します。 – ofer

+1

クライアントごとに1つのスレッドを開始しないでください。これは、実際の作業を行うよりもスケジューリングに時間がかかるため、スケーラビリティに優れていません。代わりにスレッドプールを使用してください。また、ストリームが使用されると、ストリームを閉じる必要があります(C#パターンを参照)。 –

答えて

0

巨大なリスナーのバックログを指定します。http://msdn.microsoft.com/en-us/library/5kh8wf6s.aspx

+0

。私はInt32.MaxValueにバックログを設定しようとしました - あまり役に立たなかった – ofer

+0

ええと、tcplistenerのデフォルト値はint32.maxvalueです。これはシステムのデフォルトを使用する特別な定数です。思う)。ラッキーハァッ? 10000を試してください。(出典:http://msdn.microsoft.com/en-us/library/ms739168%28VS.85%29.aspx) – fejesjoco

+0

このような状況では、「巨大な」待機バックログは必要ありません。待機中のバックログは、確立中の接続のキューのサイズを決めるために使用されます。ここでは200msごとに1つの接続がありますが、特にスケーラビリティの高いスレッド単位の接続であっても、クライアントが接続の呼び出しをブロックしているので、サーバーがクライアントよりも早く接続を受け入れることができるように設計してください。タイマーは、接続が完了するまでSTARTを開始しません... –

0

は、まず、接続のデザインごとにスレッドを使用すると、IO完了を使用して非同期サーバー・モデルにデザインをベースにした方が良いだろう、特にスケーラブルになることはほとんどありませんフードの下の港。しかし、このような場合にはサーバーにそれほど重点を置いていないため、これは問題になることはまずありません。

第2に、リッスンバックログはここで赤いニシンです。 listenバックログは、受け入れられるのを待っている接続のキューを提供するために使用されます。この例では、クライアントは同期接続呼び出しを使用します。つまり、クライアントは一度に複数の接続試行を未解決にすることはありません。クライアントで非同期接続の試行を使用していた場合は、おそらくリッスンバックログのチューニングを調べるのが適切でしょう。

第3に、クライアントコードでデータが送信されていることが示されていない場合、読み取り呼び出しを発行してそれに続くスリープを削除するだけで読み取り呼び出しがブロックされます。睡眠は問題を混乱させるだけです。

クライアントとサーバーを同じマシンで実行していますか?

このコードは、クライアントとサーバーの両方にありますか?あなたがここにあります私の自由なTCPテストクライアントを使用して問題空間からクライアントを試してみて、排除するかもしれません

:同様にhttp://www.lenholgate.com/blog/2005/11/windows-tcpip-server-performance.html

を、あなたはこのように、私のシンプルな無料のサーバーのいずれかに対して、テストクライアントをテストすることができ1つ:http://www.lenholgate.com/blog/2005/11/simple-echo-servers.html

私はコードでは明らかに間違ったものは見えません(全体的なデザインは別です)。

関連する問題