Search code examples
c#tcplistener

c# handle large number of tcp connections


I created the following simple tcp listener, but when I load the test using Apache JMeter and 500 thread, I see a 0.5% error rate. How I can improve it? How to find the reason error rate?

From Apache Jmeter I see the following error:

Response code: 500

Response message: java.net.ConnectException: Connection refused: connect

 static async Task Main(string[] args)
        {
            
            IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
            int port = 7777;

            // Create a TCP listener
            TcpListener listener = new TcpListener(ipAddress, port);
            listener.Start();
            Console.WriteLine("Server started. Waiting for connections...");

            try
            {
                while (true)
                {
                    TcpClient client = await listener.AcceptTcpClientAsync();
                

                    // Handle the client asynchronously
                    _ = HandleClientAsync(client);
                }
            }
            finally
            {
                listener.Stop();
            }
        }
      

        static async Task HandleClientAsync(TcpClient client)
        {
            try
            {
                NetworkStream stream = client.GetStream();

                byte[] buffer = new byte[1024];
                int bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length);
                string requestMessage = Encoding.ASCII.GetString(buffer, 0, bytesRead);
               // Console.WriteLine("Request message from client: " + requestMessage);
    
                // Response message
                byte[] responseData = Encoding.ASCII.GetBytes("test response");

                //Thread.Sleep(50);
                // Send the response to the client asynchronously
                await stream.WriteAsync(responseData, 0, responseData.Length);
                //Console.WriteLine("Response sent to client.");

            }
            catch (Exception ex)
            {
                Console.WriteLine("Error: " + ex.Message);
            }
            finally
            {
                // Close the connection
                client.Close();
                //Console.WriteLine("Client disconnected.");
            }

        }

enter image description here


Solution

  • You need to hand off the client to another task otherwise it blocks other clients until the first await that actually runs asynchronously is hit.

    _ = Task.Run(() => HandleClientAsync(client)); 
    

    Any further improvement is going to be marginal: it's expected that a certain amount of TCP connections can fail when load-testing, that's how the testing knows when to back off.