How to set TCPListener to always listen and when new connection discard current

10,339

Solution 1

While you are in your inner while loop, you can't check for new connections. So you would have to add something like this inside the loop:

if ( server.Pending() ) break;

That will exit your loop as soon as another connection is waiting.

Another problem is that stream.Read will block until some data is available, so new connections will not get handled if the active one is idle. So you have to change it, and not call Read unless there is some data, using stream.DataAvailable

Solution 2

This is what I'm using and it's working pretty good so far, I've just started working on this type of application. If I make any significant changes or find bugs with this code I'll update:

class ClientListener
{
    const int PORT_NO = 4500;
    const string SERVER_IP = "127.0.0.1";
    private TcpListener listener;

    public async Task Listen()
    {
        IPAddress localAddress = IPAddress.Parse(SERVER_IP);
        listener = new TcpListener(localAddress, PORT_NO);
        Console.WriteLine("Listening on: " + SERVER_IP + ":" + PORT_NO);
        listener.Start();

        while (true)
        {
            // Accept incoming connection that matches IP / Port number
            // We need some form of security here later
            TcpClient client = await listener.AcceptTcpClientAsync();

            if (client.Connected)
            {
                // Get the stream of data send by the server and create a buffer of data we can read
                NetworkStream stream = client.GetStream();
                byte[] buffer = new byte[client.ReceiveBufferSize];

                int bytesRead = stream.Read(buffer, 0, client.ReceiveBufferSize);

                // Convert the data recieved into a string
                string data = Encoding.ASCII.GetString(buffer, 0, bytesRead);
                Console.WriteLine("Recieved Data: " + data);
            }
        }
    }

    public void StopListening()
    {
        listener.Stop();
    }
}
Share:
10,339
MikeyR
Author by

MikeyR

Updated on June 05, 2022

Comments

  • MikeyR
    MikeyR almost 2 years

    I want to admit I'm not the strongest in c# and I have developed this program by looking at several tutorials, I would appreciate a lot if you can be detailed in your answer.
    I would like my TCP Server to always listening for incoming connections and when a new TCP Client connects, I want it to discard the old connection and use the new one.

    I have tried to implement this answer; https://stackoverflow.com/a/19387431/3540143
    but my issue is the fact that when I'm simulating a TCP client, but somehow the answer above will only receive one message (my current code receive all messages sent), also I've tried to convert the data over so I receive it in same way as the code below but without any success.
    Also the code above I believe is just accepting new clients, without discarding the previous connected clients.

    My current code, which can handle a connection and search for new connection once a disconnection have been made, I want to make it so I'm always looking for new connection and if a new client want to connect I'm discarding the current to let the new through

    public class TCPListener
    {
        public static void Listener()
        {
            TcpListener server = null;
            try
            {
                // Set the TcpListener on carPort.
                Int32 port = 5002;
    
                // TcpListener server = new TcpListener(port);
                server = new TcpListener(IPAddress.Any, port);
    
                // Start listening for client requests.
                server.Start();
    
                // Buffer for reading data
                Byte[] bytes = new Byte[256];
                String data = null;
    
                // Enter the listening loop.
                while (true)
                {
                    Console.Write("Waiting for a connection... ");
    
                    // Perform a blocking call to accept requests.
                    TcpClient client = server.AcceptTcpClient();
                    Console.WriteLine("Connected!");
    
                    // Get a stream object for reading
                    NetworkStream stream = client.GetStream();
    
                    int i;
    
                    // Loop to receive all the data sent by the client.
                    while ((i = stream.Read(bytes, 0, bytes.Length)) != 0)
                    {
                        // Translate data bytes to a ASCII string.
                        data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
                        Console.WriteLine("Received: {0}", data);
                    }
                    // Shutdown and end connection
                    Console.WriteLine("Client close");
                    client.Close();
                }
            }
            catch (SocketException e)
            {
                Console.WriteLine("SocketException: {0}", e);
            }
            finally
            {
                // Stop listening for new clients.
                Console.WriteLine("Stop listening for new clients.");
                server.Stop();
            }
    
        }
    }
    

    EDIT: If anyone needs the solution for my issue then this is how the code looks like when I applied what Cecilio Pardo suggested, which works really great!

    public class TCPListener
    {
        Form form = new Form();
        public static void Listener()
        {
            TcpListener server = null;
            try
            {
                // Set the TcpListener on carPort.
                Int32 port = 5002;
    
                // TcpListener server = new TcpListener(port);
                server = new TcpListener(IPAddress.Any, port);
    
                // Start listening for client requests.
                server.Start();
    
                // Buffer for reading data
                Byte[] bytes = new Byte[256];
                String data = null;
    
                // Enter the listening loop.
                while (true)
                {
                    Console.Write("Waiting for a connection... ");
    
                    // Perform a blocking call to accept requests.
                    TcpClient client = server.AcceptTcpClient();
                    Console.WriteLine("Connected!");
    
                    data = null;
                    bool dataAvailable = false;
                    // Get a stream object for reading
                    NetworkStream stream = client.GetStream();
    
                    int i;
                    while (true)
                    {
                        if (!dataAvailable)
                        {
                            dataAvailable = stream.DataAvailable;
                            //Console.WriteLine("Data Available: "+dataAvailable);
                            if (server.Pending())
                            {
                                Console.WriteLine("found new client");
                                break;
                            }
                        }
    
                        if (dataAvailable)
                        {
                            // Loop to receive all the data sent by the client.
                            i = stream.Read(bytes, 0, bytes.Length);
                            data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
    
                            Console.WriteLine("Received: {0}", data);
                            dataAvailable = false;
                        }
    
                        if (server.Pending())
                        {
                            Console.WriteLine("found new client");
                            break;
                        }
                    }
    
                    Console.WriteLine("Client close");
                    // Shutdown and end connection
                    client.Close();
                }
            }
            catch (SocketException e)
            {
                Console.WriteLine("SocketException: {0}", e);
            }
            finally
            {
                // Stop listening for new clients.
                Console.WriteLine("Stop listening for new clients.");
                server.Stop();
            }
    
        }
    }
    
  • MikeyR
    MikeyR about 8 years
    After a bit struggle, I managed to get it all to work thanks to your solution! I appreciate a lot!