我已经使用SocketAsyncEventArgs
用C#编写了高性能的TCP服务器。我一直在用两个非常简单的客户端测试它们的性能,每个客户端创建2000个并行连续循环。一个客户端使用对TcpClient
的异步调用;另一个利用同步调用。
异步
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();
}
}
});
同步
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();
}
}
});
同步版本不断迭代,没有任何错误。
但是,异步版本会导致许多No connection could be made because the target machine actively refused it
错误。我的假设是此客户端正在泛滥TCP侦听积压队列,从而导致后续的入站连接被拒绝。
这是怎么回事?如何保护服务器吞吐量免受选择异步连接的客户端的影响?
答案 0 :(得分:0)
Parallel.For
用于等待循环中所有任务的完成。但是,在异步调用的情况下,循环委托会立即完成,并返回内部异步调用的承诺。但是,外面的“没人”会等待此诺言完成,因为Parallel.For
并不是为Parallel.For
设计的,因此会导致当ConnectAsync
快速触发只能启动第一个异步操作的任务时(是 "webpack": "^4.17.1"
"json-loader": "^0.5.7",
),这很可能导致SYN泛洪。但是,由于尚未等待异步操作,还会导致其他副作用。