I'm making a simple server that listens for clients which is going to read the clients requests, do some calculations, send a response back to the client and the close again ASAP (somewhat similar to HTTP).
There might be many connections every seconds, so I want it to make it as fast and efficient as possible.
So far, the best way I can think of doing this, is shown as an example below:
private static ManualResetEvent gate = new ManualResetEvent(false);
static async void ListenToClient(TcpListener listener)
{
Console.WriteLine("Waiting for connection");
TcpClient client = await listener.AcceptTcpClientAsync();
Console.WriteLine("Connection accepted & establised");
gate.Set(); //Unblocks the mainthread
Stream stream = client.GetStream();
byte[] requestBuffer = new byte[1024];
int size = await stream.ReadAsync(requestBuffer, 0, requestBuffer.Length);
//PSEUDO CODE: Do some calculations
byte[] responseBuffer = Encoding.ASCII.GetBytes("Ok");
await stream.WriteAsync(responseBuffer, 0, responseBuffer.Length);
stream.Close();
client.Close();
}
static void Main(string[] args)
{
TcpListener listener = new TcpListener(IPAddress.Any, 8888);
listener.Start();
while (true)
{
gate.Reset();
ListenToClient(listener);
gate.WaitOne(); //Blocks the main thread and waits until the gate.Set() is called
}
}
Note: for this example and simplicity, I haven't made any error handling like try-catch and I know the response here will always be "Ok"
The code here is simply waiting for a connection, when it arrives to await listener.AcceptTcpClientAsync()
, then it jumps back to the whileloop and waits until a connection is made and gate.Set() is called so it can listen for new connections again. So this will allow multiple clients at the same time (Especially if the calculations can take long time)
But should I use stream.ReadAsync() or stream.Read() instead? Im curious if it even matters because I'm already in an asynchronous function which will not block the main thread.
So my final questions are:
- Is this the best/right way to accomplish this task (also by using ManualResetEvent class)?
- Would there be any difference in this scenario to use async or non async operations when reading and writing to the stream? (because I'm not blocking the mainthread)
- If it lags, and takes 1-2 seconds to send/receive the data, would it still matter to choose between async and nonasync operations?
UPDATE FOR NEW IMPROVEMENTS
Due to an answer, I have updated my code to this:
private static ManualResetEvent gate = new ManualResetEvent(false);
static async Task ListenToClient(TcpListener listener)
{
//Same Code
}
static void Main(string[] args)
{
TcpListener listener = new TcpListener(IPAddress.Any, 8888);
listener.Start();
while (true)
{
gate.Reset();
Task task = ListenToClient(listener);
task.ContinueWith((Task paramTask) =>
{
//Inspect the paramTask
});
gate.WaitOne(); //Blocks the main thread and waits until the gate.Set() is called
}
}