1

私は単純なtcpサーバーを作成しました-それはかなりうまく機能します。

問題は、ストレステストに切り替えると始まります-サーバーは多数の同時オープンソケットを処理する必要があるため-これをチェックするためにストレステストを作成しました。残念ながら、サーバーが窒息しているように見え、同時に開いているソケットの数が約100の場合、新しい接続要求にタイムリーに応答できません。

すでにいくつかのタイプのサーバーを試しましたが、すべて同じ動作をします。

サーバー:この投稿のサンプルのようなものにすることができます(すべて同じ動作を生成します)

スケーラブルなTcp/Ipベースのサーバーを作成する方法

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

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クライアントであり、ソケットをループして次々に開きます。

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();




        }
    }
}

この動作を説明する簡単な方法はありますか?TCPサーバーがより良い結果を生み出すのであれば、おそらくC ++の実装ですか?多分それは実際にはクライアント側の問題ですか?

コメントは大歓迎です!

ofer

4

2 に答える 2

0

まず、接続ごとのスレッドの設計が特にスケーラブルである可能性は低いため、内部でIO完了ポートを使用する非同期サーバーモデルに基づいて設計を行う方がよいでしょう。ただし、この場合、サーバーにそれほどストレスをかけているわけではないため、これが問題になる可能性はほとんどありません。

第二に、リッスンバックログはここでは赤いニシンです。リッスンバックログは、受け入れを待機している接続のキューを提供するために使用されます。この例では、クライアントは同期接続呼び出しを使用します。これは、クライアントが一度に1回を超える接続試行を未処理にすることはないことを意味します。クライアントで非同期接続の試行を使用している場合は、おそらくリッスンバックログの調整を検討するのが正しいでしょう。

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

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

これはすべてクライアントとサーバーの両方のコードですか?

http://www.lenholgate.com/blog/2005/11/windows-tcpip-server-performance.htmlで入手できる無料のTCPテストクライアントを使用して、問題のある領域からクライアントを排除しようとする場合があります

同様に、次のような単純な無料サーバーの1つに対してテストクライアントをテストできます。http://www.lenholgate.com/blog/2005/11/simple-echo-servers.html

(全体的なデザインを除いて)コードに明らかに問題があることは何もわかりません。

于 2010-12-29T20:06:11.023 に答える
0

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

于 2010-12-29T14:59:08.113 に答える