AcceptTcpClientAsync 在多个连接上滞后
AcceptTcpClientAsync lagging on multiply connections
我有一个服务器和一个通过 tcp 连接的客户端。
如果同时向服务器发送多个连接请求,则首先快速创建多个连接,然后客户端以大约一秒的间隔开始连接。
我只发现了一个依赖项,即有多少个处理器内核就能快速连接多少个客户端。
服务器代码:
class Program {
static void Main(string[] args) {
var loggerFactory = new LoggerFactory().AddNLog();
var logger = loggerFactory.CreateLogger<Program>();
var tcpListener = new TcpListener(IPAddress.Any, 9100);
tcpListener.Start();
var sem = new SemaphoreSlim(18, 18);
while (true) {
sem.Wait();
tcpListener
.AcceptTcpClientAsync()
.ContinueWith(async task => {
logger.LogInformation("Client accepted");
sem.Release();
});
}
}
}
客户代码:
class Program {
static void Main(string[] args) {
var loggerFactory = new LoggerFactory().AddNLog();
var logger = loggerFactory.CreateLogger<Program>();
var clientCount = 100;
for (int i = 0; i < clientCount; i++) {
Task.Run(() => {
var guid = Guid.NewGuid();
var client = new TcpClient();
client.Connect(IPAddress.Loopback, 9100);
logger.LogInformation($"{guid} Connected");
Thread.Sleep(1000000);
});
}
while (true) { }
}
}
服务器日志(Windows10 x64/6 cores/netcore2.2):
2019/04/24 10:59:50.270|INFO|Test.Server.Tcp.Program|Client accepted
2019/04/24 10:59:50.295|INFO|Test.Server.Tcp.Program|Client accepted
2019/04/24 10:59:50.296|INFO|Test.Server.Tcp.Program|Client accepted
2019/04/24 10:59:50.296|INFO|Test.Server.Tcp.Program|Client accepted
2019/04/24 10:59:50.297|INFO|Test.Server.Tcp.Program|Client accepted
2019/04/24 10:59:50.297|INFO|Test.Server.Tcp.Program|Client accepted
2019/04/24 10:59:51.252|INFO|Test.Server.Tcp.Program|Client accepted
2019/04/24 10:59:52.252|INFO|Test.Server.Tcp.Program|Client accepted
2019/04/24 10:59:53.252|INFO|Test.Server.Tcp.Program|Client accepted
2019/04/24 10:59:54.252|INFO|Test.Server.Tcp.Program|Client accepted
2019/04/24 10:59:55.252|INFO|Test.Server.Tcp.Program|Client accepted
服务器日志(Kubuntu x64/8 cores/netcore2.2)
2019/04/24 11:17:42.464|INFO|Test.Server.Tcp.Program|Client accepted
2019/04/24 11:17:42.464|INFO|Test.Server.Tcp.Program|Client accepted
2019/04/24 11:17:42.464|INFO|Test.Server.Tcp.Program|Client accepted
2019/04/24 11:17:42.464|INFO|Test.Server.Tcp.Program|Client accepted
2019/04/24 11:17:42.464|INFO|Test.Server.Tcp.Program|Client accepted
2019/04/24 11:17:42.464|INFO|Test.Server.Tcp.Program|Client accepted
2019/04/24 11:17:42.464|INFO|Test.Server.Tcp.Program|Client accepted
2019/04/24 11:17:42.464|INFO|Test.Server.Tcp.Program|Client accepted
2019/04/24 11:17:50.937|INFO|Test.Server.Tcp.Program|Client accepted
2019/04/24 11:17:59.941|INFO|Test.Server.Tcp.Program|Client accepted
2019/04/24 11:18:09.943|INFO|Test.Server.Tcp.Program|Client accepted
2019/04/24 11:18:21.446|INFO|Test.Server.Tcp.Program|Client accepted
2019/04/24 11:18:33.449|INFO|Test.Server.Tcp.Program|Client accepted
如何加快客户端连接速度?
使用 TaskCreationOptions.LongRunning 的工作客户端代码:
class Program {
static void Main(string[] args) {
var loggerFactory = new LoggerFactory().AddNLog();
var logger = loggerFactory.CreateLogger<Program>();
var clientCount = 100;
for (int i = 0; i < clientCount; i++) {
var client = new TcpClient();
client
.ConnectAsync(IPAddress.Loopback, 9100)
.ContinueWith(async task => {
await task;
logger.LogInformation("Connected");
await Task.Delay(1000000); // a lot of work
}, TaskContinuationOptions.LongRunning);
}
while (true) { }
}
}
我有一个服务器和一个通过 tcp 连接的客户端。 如果同时向服务器发送多个连接请求,则首先快速创建多个连接,然后客户端以大约一秒的间隔开始连接。
我只发现了一个依赖项,即有多少个处理器内核就能快速连接多少个客户端。
服务器代码:
class Program {
static void Main(string[] args) {
var loggerFactory = new LoggerFactory().AddNLog();
var logger = loggerFactory.CreateLogger<Program>();
var tcpListener = new TcpListener(IPAddress.Any, 9100);
tcpListener.Start();
var sem = new SemaphoreSlim(18, 18);
while (true) {
sem.Wait();
tcpListener
.AcceptTcpClientAsync()
.ContinueWith(async task => {
logger.LogInformation("Client accepted");
sem.Release();
});
}
}
}
客户代码:
class Program {
static void Main(string[] args) {
var loggerFactory = new LoggerFactory().AddNLog();
var logger = loggerFactory.CreateLogger<Program>();
var clientCount = 100;
for (int i = 0; i < clientCount; i++) {
Task.Run(() => {
var guid = Guid.NewGuid();
var client = new TcpClient();
client.Connect(IPAddress.Loopback, 9100);
logger.LogInformation($"{guid} Connected");
Thread.Sleep(1000000);
});
}
while (true) { }
}
}
服务器日志(Windows10 x64/6 cores/netcore2.2):
2019/04/24 10:59:50.270|INFO|Test.Server.Tcp.Program|Client accepted
2019/04/24 10:59:50.295|INFO|Test.Server.Tcp.Program|Client accepted
2019/04/24 10:59:50.296|INFO|Test.Server.Tcp.Program|Client accepted
2019/04/24 10:59:50.296|INFO|Test.Server.Tcp.Program|Client accepted
2019/04/24 10:59:50.297|INFO|Test.Server.Tcp.Program|Client accepted
2019/04/24 10:59:50.297|INFO|Test.Server.Tcp.Program|Client accepted
2019/04/24 10:59:51.252|INFO|Test.Server.Tcp.Program|Client accepted
2019/04/24 10:59:52.252|INFO|Test.Server.Tcp.Program|Client accepted
2019/04/24 10:59:53.252|INFO|Test.Server.Tcp.Program|Client accepted
2019/04/24 10:59:54.252|INFO|Test.Server.Tcp.Program|Client accepted
2019/04/24 10:59:55.252|INFO|Test.Server.Tcp.Program|Client accepted
服务器日志(Kubuntu x64/8 cores/netcore2.2)
2019/04/24 11:17:42.464|INFO|Test.Server.Tcp.Program|Client accepted
2019/04/24 11:17:42.464|INFO|Test.Server.Tcp.Program|Client accepted
2019/04/24 11:17:42.464|INFO|Test.Server.Tcp.Program|Client accepted
2019/04/24 11:17:42.464|INFO|Test.Server.Tcp.Program|Client accepted
2019/04/24 11:17:42.464|INFO|Test.Server.Tcp.Program|Client accepted
2019/04/24 11:17:42.464|INFO|Test.Server.Tcp.Program|Client accepted
2019/04/24 11:17:42.464|INFO|Test.Server.Tcp.Program|Client accepted
2019/04/24 11:17:42.464|INFO|Test.Server.Tcp.Program|Client accepted
2019/04/24 11:17:50.937|INFO|Test.Server.Tcp.Program|Client accepted
2019/04/24 11:17:59.941|INFO|Test.Server.Tcp.Program|Client accepted
2019/04/24 11:18:09.943|INFO|Test.Server.Tcp.Program|Client accepted
2019/04/24 11:18:21.446|INFO|Test.Server.Tcp.Program|Client accepted
2019/04/24 11:18:33.449|INFO|Test.Server.Tcp.Program|Client accepted
如何加快客户端连接速度?
使用 TaskCreationOptions.LongRunning 的工作客户端代码:
class Program {
static void Main(string[] args) {
var loggerFactory = new LoggerFactory().AddNLog();
var logger = loggerFactory.CreateLogger<Program>();
var clientCount = 100;
for (int i = 0; i < clientCount; i++) {
var client = new TcpClient();
client
.ConnectAsync(IPAddress.Loopback, 9100)
.ContinueWith(async task => {
await task;
logger.LogInformation("Connected");
await Task.Delay(1000000); // a lot of work
}, TaskContinuationOptions.LongRunning);
}
while (true) { }
}
}