Home > Software engineering >  Why does this application not hang and how is it waiting for a client to connect?
Why does this application not hang and how is it waiting for a client to connect?

Time:09-19

I am learning some basic C# programming.

Was following a tutorial and the main function has a loop like this:

class Server
{
    static List<Client> _clients = new();
    static TcpListener _listener = new(IPAddress.Parse("127.0.0.1"),7892);
    
    static void Main(string[] args) 
    {
        _listener.Start();

        while (true)
        {
            var client = new Client(_listener.AcceptTcpClient());
            _clients.Add(client);
            Console.WriteLine(_clients.Count  " total clients");
        }
    }
}

Since this is an infinite never ending while loop, why does the program not hang like it does when I accidently create an infinite loop in other scripts?

Additionally, when I ran this code, I was surprised to find it was not adding a new client every loop, but only when a client connected, how exactly is it waiting on the AcceptTcpClient() function? I looked at the code for this function, its not clear to me how its waiting...

public TcpClient AcceptTcpClient()
{
    if (!_active)
    {
        throw new InvalidOperationException(SR.net_stopped);
    }

    Socket acceptedSocket = _serverSocket!.Accept();
    return new TcpClient(acceptedSocket);
}

CodePudding user response:

Hint: in the future, putting a debugger breakpoint can help you find out why easily.

The AcceptTcpClient method is a blocking call, similar to Console.ReadLine():

// Perform a blocking call to accept requests.
// You could also use server.AcceptSocket() here.
TcpClient client = server.AcceptTcpClient();

So while your while loop would run forever, it doesn't consume resources (usually CPU) continously like this loop:

while (true) i  ;

If you put a debugger, you will notice it stops at AcceptTcpClient until a client connects. That's why your program doesn't freeze since it's waiting and not doing anything. However note that if you do this in an UI thread of a WPF app for example, the GUI would probably freeze since it blocks the thread.

If you are curious about how blocking function is implemented, this question is probably the closest I could find on SO but nowadays people generally want to avoid it (since it blocks your thread) and try making things asynchronous (using Task) instead. You should actually use AcceptTcpClientAsync if possible.

  •  Tags:  
  • c#
  • Related