So I have a TcpClient in a console app that is listening on port 9096. I want the client to be able to handle multiple connections (simultaneous or not). I also do not want to use Threads. I want to use async/await. I also need to be able to gracefully close the app during certain events, being careful not to lose any data. So I need a cancellation token. I have the code mostly working but there are two issues.
First, when the app starts listening and I send it data; everything works correctly as long as the sender is using the same initial connection to the app. Once a new connection (or socket I guess? not clear on the terminology) is established the app does not process the new data.
Second, when the terminate signal is given to the app and the token is canceled the app does not close. I am not getting any exceptions and I cannot figure out what I an doing wrong.
I have looked all over and cannot find an example of a TcpClient that uses async/await with a cancellation token. I also cannot find an example that I have been able to get working that correctly processes multiple connections, without using Threads or other complicated designs. I want the design as simple as possible with as little code as possible while still meeting my requirements. If using threads is the only way to do it I will, but I am soo close to getting it right I feel like I am just missing a little thing.
I am trying to figure this out at my wits end and have exhausted all my ideas.
EDIT: I moved the AcceptTcpClientAsync into the loop as suggested below and it did not change anything. The app functions the same as before.
Program.cs
class Program { private static List<Task> _listeners = new List<Task>(); private static readonly CancellationTokenSource cancelSource = new CancellationTokenSource(); static void Main(string[] args) { Console.TreatControlCAsInput = false; Console.CancelKeyPress += (o, e) => { Console.WriteLine("Shutting down."); cancelSource.Cancel(); }; Console.WriteLine("Started, press ctrl + c to terminate."); _listeners.Add(Listen(cancelSource.Token)); cancelSource.Token.WaitHandle.WaitOne(); Task.WaitAll(_listeners.ToArray(), cancelSource.Token); } } Listen
public async Task Listen(CancellationToken token){ var listener = new TcpListener(IPAddress.Parse("0.0.0.0"), 9096); listener.Start(); Console.WriteLine("Listening on port 9096"); while (!token.IsCancellationRequested) { // Also tried putting AcceptTcpClientAsync here. await Task.Run(async () => { var client = await listener.AcceptTcpClientAsync(); using (var stream = client.GetStream()) using (var streamReader = new StreamReader(stream, Encoding.UTF8)) using (var streamWriter = new StreamWriter(stream, Encoding.UTF8)) { while (!token.IsCancellationRequested) { // DO WORK WITH DATA RECEIVED vat data = await streamReader.ReadAsync(); await streamWriter.WriteLineAsync("Request received."); } } }); } Console.WriteLine("Stopped Accepting Requests."); listener.Server.Close(); listener.Stop(); }