Search code examples
c#tcptcplistener

Why is TcpListener never accepting the TcpClient?


I have a device that acts as a TcpClient and sends TCP packets to a set IP on my network.

When I run the standard TcpListener program (from the official documentation), it gets stuck in the server.AcceptTcpClient() instruction, never being able to actually detect the connection.

I have used Wireshark to check if the packets were actually being sent, and they are.

I have checked that packets are TCP and that the SYN is being sent. They are marked as duplicate ports since they are never accepted by the host.

This is my code (copied and slightly modified from the MS documentation above).

public static class Connection
    {
        public static void Connect(int port)
        {
            TcpListener server = null;
            try
            {
                IPAddress localAddress = IPAddress.Parse("127.0.0.1");
                server = new(localAddress, port);

                // Start listening for clients
                server.Start();

                // Listening loop
                while (true)
                {
                    Console.WriteLine("Waiting for connection...");

                    // Wait for client to connect
                    TcpClient client = server.AcceptTcpClient(); // NEVER UNBLOCKS

                    // Close connection
                    client.Close();
                }
            }
            catch (SocketException e)
            {
                Console.WriteLine("Socket exception: ", e);
            }
            finally
            {
                // Stop listening for clients
                server.Stop();
            }
        }
    }

Solution

  • To bind to the outgoing network adapter, rather than the loopback, use IPAddress.Any

    server = new(IPAddress.Any, port);
    

    You are also mising using in various place, and ideally you should use async. There also efficiencies you can make with reusing the same buffer.

    public static async Task Connect(int port)
    {
        TcpListener server = null;
        try
        {
            server = new(IPAddress.Any, port);
    
            // Empezar a escuchar peticiones de clientes
            server.Start();
    
            // Buffer para leer datos
            Byte[] buffer = new Byte[256];
            string data = "";
    
            // Entrar al bucle de escucha
            while (true)
            {
                Console.WriteLine("Esperando conexión...");
    
                // Bloquear el programa hasta aceptar una petición
                using TcpClient client = await server.AcceptTcpClientAsync();
                Console.WriteLine("Conectado!");
                data = "";
    
                // Crear una trama para leer y escribir
                using NetworkStream stream = client.GetStream();
                int i;
    
                // Recibir todos los datos del cliente
                while ((i = await stream.ReadAsync(buffer, 0, buffer.Length)) != 0)
                {
                    data = System.Text.Encoding.ASCII.GetString(buffer, 0, i);
                    Console.WriteLine($"Recibido: {data}");
    
                    // Procesar los datos enviados por el cliente
                    data = data.ToUpper();
                    i = System.Text.Encoding.ASCII.GetBytes(data, 0, data.Length, buffer, 0);
    
                    // Enviar una respuesta
                    await stream.WriteAsync(buffer, 0, i);
                    Console.WriteLine($"Devuelto: {data}");
                }
    
                // Terminar la conexión
            }
        }
        catch (SocketException e)
        {
            Console.WriteLine("Socket exception: ", e);
        }
        finally
        {
            // Dejar de escuchar clientes
            if(server?.Active)
                server.Stop();
        }
    }
    

    Note that the above code will only deal with one client at a time. If you want to deal with multiple, you need to hand off the TcpClient to a Task.Run task.