Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/281.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在.net中处理大量TCP客户端连接_C#_.net_Sockets_Networking_Tcp - Fatal编程技术网

C# 在.net中处理大量TCP客户端连接

C# 在.net中处理大量TCP客户端连接,c#,.net,sockets,networking,tcp,C#,.net,Sockets,Networking,Tcp,我需要构建一个应用程序(服务器),处理通过TCP从客户端发送的数据。我必须能够支持(至少)2000个连接。我曾尝试编写TCP服务器,但我发现当我开始达到600/700连接时,服务器的响应速度会大大降低(随着接收到越来越多的连接,响应速度实际上会随着时间的推移而降低)。我通常不写网络代码,所以我确信有很多概念我还没有完全理解,可以改进 我的服务器的主要用途是: 处理从客户端发送的数据并将其存储在sql数据库中 决定(基于) 收到最后一条消息后)应向客户机提供什么样的正确响应 将响应列表和 一次发送

我需要构建一个应用程序(服务器),处理通过TCP从客户端发送的数据。我必须能够支持(至少)2000个连接。我曾尝试编写TCP服务器,但我发现当我开始达到600/700连接时,服务器的响应速度会大大降低(随着接收到越来越多的连接,响应速度实际上会随着时间的推移而降低)。我通常不写网络代码,所以我确信有很多概念我还没有完全理解,可以改进

我的服务器的主要用途是:

  • 处理从客户端发送的数据并将其存储在sql数据库中
  • 决定(基于) 收到最后一条消息后)应向客户机提供什么样的正确响应
  • 将响应列表和 一次发送一个给客户机
  • 所有客户都需要这样做。下面是我实现的代码:

        private readonly TcpListener tcpListener;
        private readonly Thread listenThread;    
        private bool run = true;
    
        public Server()
        {
             this.tcpListener = new TcpListener(IPAddress.Any, AppSettings.ListeningPort); //8880 is default for me.
             this.listenThread = new Thread(new ThreadStart(ListenForClients));
             this.listenThread.Start();
        }
    
        private void ListenForClients()
        {
             this.tcpListener.Start();
    
             while (run) {
                  TcpClient client = this.tcpListener.AcceptTcpClient();
    
                  //create a thread to handle communication with connected client
                  Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
                  clientThread.Start(client);
              }
        }
        private void HandleClientComm(object client)
        {
            Queue responseMessages = new Queue();
            while (run)
            {
                try
                {
                    lastMessage = clientStream.GetMessage();
    
                    if (lastMessage.Length > 0)
                    {
                        // Process logic here...  
                        //an item may be added to the response queue, depending on logic.
                    }
    
                    if (responseMessages.Count > 0)
                    {
                       clientStream.WriteMessage(msg);
                       clientStream.Flush();
    
                       // sleep for 250 milliseconds (or whats in the config).
                       Thread.Sleep(AppSettings.MessageSendDelayMilliseconds); 
                    }
                }
                catch (Exception ex)
                {
                    break;
                }
            }
            tcpClient.Close();
        }
    
    最后,我写了一个扩展类来帮助我:

    namespace System.Net.Sockets
    {
        using System.Text;
    
        public static class NetworkSteamExtension
        {
            private static readonly ASCIIEncoding Encoder = new ASCIIEncoding();
    
            public static string GetMessage(this NetworkStream clientStream)
            {
                string message = string.Empty;
                try
                {
                    byte[] bMessage = new byte[4068];
                    int bytesRead = 0;
                    while (clientStream.DataAvailable)
                    {
                        bytesRead = clientStream.Read(bMessage, 0, 4068);
                        message += Encoder.GetString(bMessage, 0, bytesRead);
                    }
                }
                catch (Exception)
                {
    
                }
                return message;         
            }
    
            public static void WriteMessage(this NetworkStream clientStream, string message)
            {
                byte[] buffer = Encoder.GetBytes(message);
                clientStream.Write(buffer, 0, buffer.Length);
                clientStream.Flush();
            }
        }
    }
    
    关于这个主题的很多文章人们都在使用套接字。我还了解到.NET4.5Async/await是实现解决方案的最佳方式

    我想确保利用.net中的最新功能(如果有帮助的话,甚至是4.5.2),构建一个至少可以处理2000个连接的服务器。有人能提供建议吗


    非常感谢

    好的,我们需要修复一些API使用错误,然后是创建太多线程的主要问题。众所周知,许多连接只能通过异步IO有效处理。数百个连接被视为“太多”

    客户端处理循环必须是异步的。重写HandleClientComm,使其使用异步套接字IO。这很容易等待。您需要在web上搜索“.net套接字等待”

    您可以继续使用同步接受调用。没有坏处。保持简单的同步代码。仅对具有重要
    avgWaitTime*countPerSecond
    产品的调用进行异步。这通常是所有套接字调用

    假设
    DataAvailable
    返回任何给定消息中的字节数。TCP不保留消息边界。你需要自己去做。
    DataAvailable
    值几乎没有意义,因为它可能会低估未来将到达的真实数据

    通常最好使用更高级别的序列化协议。例如,带有长度前缀的protobuf。不要使用ASCII码。您这样做可能只是因为您不知道如何使用“真实”编码

    使用
    处理所有资源。不要使用非通用的
    队列
    类。不要刷新流,这对套接字没有任何作用


    为什么要睡觉?

    看起来您为每个客户端连接启动了一个线程。这将是600/700线程在您的进程中,所有需要得到一个时间片。。。。检查你想做的每件事的方法。那么你认为我所需要的只是一行的改变吗?从“TcpClient client=this.tcpListener.AcceptTcpClient();”到“Task client=this.tcpListener.AcceptTcpClientAsync();”?或者还有更多?听起来像是一个潜在的用途。这个框架使它易于扩展并处理异步和线程的所有复杂性。谢谢@usr-你提出了很多(好的)建议!正如我提到的,我对这种类型的编程非常陌生,示例对我非常有帮助!:-)例如,您说过不要使用Queue类-我可以使用哪些替代方案?转换的“真实”编码方式是什么。顺便说一句,睡眠只是为了确保客户端不会因为响应而慌乱(这是我们使用的客户端的一个缺点)。使用
    Queue
    。更好的编码是UTF8,但这更难,因为UTF8字节字符串不能在任意边界上拆分。睡眠-好的,这是一个很好的睡眠案例。使用Task.Delay@usr您让它听起来很简单;-)忙着自己写一本。。。我同意你的观点。。我在做运动时要问的问题。我已经写了代码。。。但我知道有些事情不对劲只是不确定。。。最佳实践。。。我不知道什么味道。。。我相信这是因为它适用于许多线程。。。但我认为线程池可以处理这个问题。你可能有gd参考我可以读。太多的线程意味着你正在阻塞。提出一个问题并在此处留下链接@Seabizkit