【问题标题】:getting 10060 (Connection Timed Out) when stress testing simple tcp server压力测试简单 tcp 服务器时得到 10060(连接超时)
【发布时间】:2010-12-29 14:36:18
【问题描述】:

我已经创建了简单的 tcp 服务器 - 它运行良好。

当我们切换到压力测试时问题就开始了——因为我们的服务器应该处理许多并发打开的套接字——我们创建了一个压力测试来检查这一点。 不幸的是,当并发打开的套接字数量在 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 客户端,一个接一个地循环和打开套接字

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++ 实现?也许这实际上是一个客户端问题?

欢迎任何评论!

报价

【问题讨论】:

  • 你在什么操作系统上测试?你不应该为每个连接都创建一个新线程,你应该考虑使用异步接口来实现一般的可伸缩性,请参阅 BeginAccept、BeginReceive 等。
  • win 7. 我知道异步方法更可取。但是,上述行为发生在我尝试过的任何服务器实现上——包括回调 ..
  • 您不应为每个客户端启动一个线程。这不能很好地扩展,因为该过程将花费更多的时间来安排而不是实际工作。请改用线程池。您还应该在使用 Streams 后关闭它们(查看 C# using 模式)。
  • 首先,正如其他人所指出的,不要为每个连接创建一个线程。使用异步 API。即使您的服务器没有做任何其他事情(例如,提供内容),您在任何 32 位进程中都将被限制为 around 2000 threads。其次,请编辑您的问题,提供以下信息:操作系统(是的,这非常重要)和您收到的错误消息(以及您在哪里获得)。

标签: c# .net sockets winsock winsock2


【解决方案1】:

指定一个巨大的侦听器积压:http://msdn.microsoft.com/en-us/library/5kh8wf6s.aspx

【讨论】:

  • 好吧。我尝试将积压工作设置为 Int32.MaxValue - 没有多大帮助
  • 是的,tcplistener 也默认为 int32.maxvalue,它恰好是一个使用系统默认值的特殊常量,我猜大概是 100(我认为是 128)。幸运吧?尝试 10000。(来源:msdn.microsoft.com/en-us/library/ms739168%28VS.85%29.aspx)
  • 在这种情况下,您不应该需要“巨大的”收听积压。侦听积压用于确定正在建立的连接队列的大小。这里我们每 200 毫秒有一个连接,即使不是特别可扩展,每个连接的线程,设计服务器应该能够比客户端启动它们更快地接受连接,特别是因为客户端正在发出阻塞连接调用,所以 200 毫秒在连接完成之前,计时器甚至不会开始......
【解决方案2】:

首先,每个连接的线程设计不太可能特别具有可扩展性,您最好将设计基于使用 IO 完成端口的异步服务器模型。但是,在这种情况下,这不太可能成为问题,因为您并没有真正对服务器施加太大压力。

其次,收听积压是一个红鲱鱼。侦听积压用于为等待接受的连接提供队列。在此示例中,您的客户端使用同步连接调用,这意味着客户端在任何时候都不会有超过 1 次未完成的连接尝试。如果您在客户端中使用异步连接尝试,那么您可能会考虑调整侦听积压。

第三,鉴于客户端代码没有显示它发送任何数据,您可以简单地发出读取调用并移除其后的睡眠,读取调用将阻塞。睡眠只会让事情变得混乱。

您是否在同一台机器上运行客户端和服务器?

这是客户端和服务器中的所有代码吗?

您可以尝试使用我的免费 TCP 测试客户端从问题空间中消除客户端,该客户端可在此处获得:http://www.lenholgate.com/blog/2005/11/windows-tcpip-server-performance.html

同样,您可以针对我的一台简单的免费服务器测试您的测试客户端,例如:http://www.lenholgate.com/blog/2005/11/simple-echo-servers.html

我看不出代码有任何明显错误(除了整体设计)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-05-26
    • 1970-01-01
    • 2020-04-18
    • 2011-12-29
    • 1970-01-01
    • 2020-06-03
    • 2014-11-14
    • 1970-01-01
    相关资源
    最近更新 更多