I have written a high performance TCP server in C# using SocketAsyncEventArgs
. I have been testing its performance with two very simple clients, each creating 2000 parallel continuous loops. One client makes use of asynchronous calls to TcpClient
; the other makes use of synchronous calls.
Asynchronous
Parallel.For(0, numClients, parallelOptions, async i =>
{
while (true)
{
var tcpClient = new TcpClient();
try
{
await tcpClient.ConnectAsync(host, port);
await tcpClient.GetStream().WriteAsync(message);
var buffer = new byte[1024];
await tcpClient.GetStream().ReadAsync(buffer, 0, 1024);
tcpClient.GetStream().Close();
}
catch (Exception ex)
{
Console.WriteLine($"{DateTime.Now.ToLongTimeString()}: {ex.Message}");
}
finally
{
tcpClient.Close();
tcpClient.Dispose();
}
}
});
Synchronous
Parallel.For(0, numClients, parallelOptions, i =>
{
while (true)
{
var tcpClient = new TcpClient();
try
{
tcpClient.Connect(host, port);
tcpClient.GetStream().Write(message);
var buffer = new byte[1024];
tcpClient.GetStream().Read(buffer, 0, 1024);
tcpClient.GetStream().Close();
}
catch (Exception ex)
{
Console.WriteLine($"{DateTime.Now.ToLongTimeString()}: {ex.Message}");
}
finally
{
tcpClient.Close();
tcpClient.Dispose();
}
}
});
The synchronous version iterates continuously without any errors.
The asynchronous version, however, results in many No connection could be made because the target machine actively refused it
errors. My assumptions are that this client is flooding the TCP listen backlog queue, causing subsequent inbound connections to be rejected.
What's going on? How can I protect server throughput from clients that choose to connect asynchronously?