Accept TCP Client Async

I've been making a server. I am using TcpListener.AcceptTcpClientAsync() in an async method, but I have no idea how to actually make it work. My code right now is:

private static async void StartServer()
{
    Console.WriteLine("S: Server started on port {0}", WebVars.ServerPort);
    var listener = new TcpListener(WebVars.LocalIp, WebVars.ServerPort);
    listener.Start();
    var client = await listener.AcceptTcpClientAsync();
}

How do I process the client? Do I just continue coding and it will automagically make new threads of the same method or do I need to do some magic method that will do it for me?

Edit: current code:

private static Task HandleClientAsync(TcpClient client)
{
    var stream = client.GetStream();
    // do stuff
}
/// <summary>
/// Method to be used on seperate thread.
/// </summary>
private static async void RunServerAsync()
{
    while (true)
    {
        Console.WriteLine("S: Server started on port {0}", WebVars.ServerPort);
        var listener = new TcpListener(WebVars.LocalIp, WebVars.ServerPort);
        listener.Start();
        var client = await listener.AcceptTcpClientAsync();
        await HandleClientAsync(client);
    }
}
Jon Skeet
people
quotationmark

Nothing will magically create dedicated threads for you, although there are some threads used for IO completion which can come into play, particularly if you don't have a synchronization context that you need to return to.

You should decide whether you want your StartServer method to actually complete when it's accepted a single connection, or keep looping until you've been told to shut down.

Either way, you clearly need to decide how to handle the client too. Either you could start a new thread and use synchronous methods, or you could just use asynchronous IO to handle everything in the same thread. For example, to dump the incoming data to a file:

private Task HandleClientAsync(TcpClient client)
{
    // Note: this uses a *synchronous* call to create the file; not ideal.
    using (var output = File.Create("client.data"))
    {
        using (var input = client.GetStream())
        {
            // Could use CopyToAsync... this is just demo code really.

            byte[] buffer = new byte[8192];
            int bytesRead;
            while ((bytesRead = await input.ReadAsync(buffer, 0, buffer.Length)) > 0)
            {
                await output.WriteAsync(buffer, 0, bytesRead);
            }
        }
    }
}

(That's assuming the client will just terminate the connection when it's finished writing the data.) Aside from the File.Create call, this is all asynchronous - so there's no need to create a separate thread for it.

This is just an example, of course - real connection handling would usually be more complicated. If your real handling needs anything more compute-intensive, you may well want to consider using Task.Run to use the thread pool... that way it won't interfere with accepting more connections.

people

See more on this question at Stackoverflow