对简单 tcp 服务器进行压力测试时出现 10060(连接超时)

发布于 2024-10-10 05:37:57 字数 2779 浏览 4 评论 0原文

我创建了简单的 TCP 服务器 - 它运行得很好。

当我们切换到压力测试时,问题就开始了 - 因为我们的服务器应该处理许多并发的打开套接字 - 我们创建了一个压力测试来检查这一点。 不幸的是,当并发打开套接字的数量约为 100 时,看起来服务器很卡,无法及时响应新的连接请求。

我们已经尝试了几种类型的服务器 - 并且都产生相同的行为。

服务器:可以类似于本文中的示例(都产生相同的行为)

如何编写基于 Tcp/Ip 的可扩展服务器

这是我们正在使用的代码 - 当客户端连接时 - 服务器将挂起以保持套接字处于活动状态。

enter code here

public class Server

{
    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客户端,循环并打开socket,一个接一个

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




        }
    }
}

有没有简单的方法来解释这种行为?也许C++实现如果TCP服务器会产生更好的结果?也许这实际上是客户端问题?

任何评论都将受到欢迎!

提供

I have created simple tcp server - it works pretty well.

the problems starts when we switch to the stress tests -since our server should handle many concurrent open sockets - we have created a stress test to check this.
unfortunately, looks like the server is choking and can not respond to new connection request in timely fashion when the number of the concurrent open sockets are around 100.

we already tried few types of server - and all produce the same behavior.

the server: can be something like the samples in this post(all produce the same behavior)

How to write a scalable Tcp/Ip based server

here is the code that we are using - when a client connects - the server will just hang in order to keep the socket alive.

enter code here

public class Server

{
    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);
        }
    }
}

the stress test client: is a simple tcp client, that loop and open sokets, one after the other

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




        }
    }
}

is there an easy way to explain this behavior? maybe c++ implementation if the TCP server will produce better results? maybe it is actually a client side problem?

Any comment will be welcomed !

ofer

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

一笔一画续写前缘 2024-10-17 05:37:57

首先,每个连接的线程设计不太可能具有特别的可扩展性,您最好将设计基于异步服务器模型,该模型在后台使用 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 lenholgate.com/blog/2005/11/simple-echo-servers.html

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

Firstly a thread per connection design is unlikely to be especially scalable, you would do better to base your design on an asynchronous server model which uses IO Completion Ports under the hood. This, however, is unlikely to be the problem in this case as you're not really stressing the server that much.

Secondly the listen backlog is a red herring here. The listen backlog is used to provide a queue for connections that are waiting to be accepted. In this example your client uses a synchronous connect call which means that the client will never have more than 1 connect attempt outstanding at any one time. If you were using asynchronous connection attempts in the client then you would be right to look at tuning the listen backlog, perhaps.

Thirdly, given that the client code doesn't show that it sends any data, you can simply issue the read calls and remove the sleep that follows it, the read calls will block. The sleep just confuses matters.

Are you running the client and the server on the same machine?

Is this ALL the code in both client and server?

You might try and eliminate the client from the problem space by using my free TCP test client which is available here: http://www.lenholgate.com/blog/2005/11/windows-tcpip-server-performance.html

Likewise, you could test your test client against one of my simple free servers, like this one: http://www.lenholgate.com/blog/2005/11/simple-echo-servers.html

I can't see anything obviously wrong with the code (apart from the overall design).

高冷爸爸 2024-10-17 05:37:57

我将 MTU 从 1500 降低到 1300,似乎有帮助。

I lowered MTU from 1500 to 1300, seemed to help.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文