StreamWriter ReadLine method hangs program

I am trying to get some basic multi-threading working in C#. There's no clear tutorial that I've found so bear with my sub-par code:

class Program
{
    private static TcpListener listener;
    private static List<TcpClient> clients; 
    static void Main(string[] args)
    {
        listener = new TcpListener(IPAddress.Any, 1337);
        clients = new List<TcpClient>();
        StartListening();
        Console.WriteLine("Accepting clients..");
        Console.WriteLine("Press any key to exit");
        Console.ReadKey();
    }

    static async void StartListening()
    {
        listener.Start();
        while (true)
        {
            clients.Add(await listener.AcceptTcpClientAsync().ConfigureAwait(false));
            Console.WriteLine("Client connected!");
            HandleClient(clients[clients.Count - 1], clients.Count);
        }
    }

    static async void HandleClient(TcpClient c, int number)
    {
        Console.WriteLine($"Getting client #{number}'s handshake..");
        var ns = c.GetStream();
        var sr = new StreamReader(ns);
        var handshake = sr.ReadLine();
        Console.WriteLine("Client {0}'s handshake: {1}", number, handshake);
    }
}

Right, so what I'm trying to achieve in the server program is:

 1. Accepting client
 2. Receiving handshake, print it to console
 3. Add to the clients list

The accepting client part works, however the program just stops just after the first line of HandleClient(). I've tried waiting for absurd amounts of time (1000ms) and even then it just doesn't receive anything, nor does it throw an exception (i.e. it stays connected). What am I doing wrong here?

Client code is here if you need it!

Jon Skeet
people
quotationmark

Your client code is broken here - you're never flushing it:

var sw = new StreamWriter(ns);
Thread.Sleep(1000);
sw.WriteLine(handshake);

There's no need for the Thread.Sleep call, but you should flush the StreamWriter if you want the data to actually be sent to the network layer immediately:

sw.Flush();

While (as Stephen Cleary notes) this wouldn't mean it necessarily got sent immediately, it's reasonable to expect it to be sent "reasonably soon" after flushing.

people

See more on this question at Stackoverflow