【发布时间】:2021-07-15 14:47:59
【问题描述】:
我有一个服务器应用程序来接受来自一组大约 10000 个客户端(实际上是具有 GPRS 接口的现场设备)的 TCP 连接。
接受连接的部分是这样的:
public async System.Threading.Tasks.Task AcceptConnections()
{
_listenerProxy.StartListen();
var taskList = new List<System.Threading.Tasks.Task>();
var application = _configManager.Configuration.GetSection("application");
var maxTasks = int.Parse(application["MaxTasksPerListener"]);
while (true)
{
if (taskList.Count > maxTasks)
{
_logger.Info($"Waiting for handling task to be completed {_listenerProxy.Port}.");
await System.Threading.Tasks.Task.WhenAny(taskList.ToArray()).ConfigureAwait(false);
taskList.RemoveAll(t => t.IsCompleted); // at least one task affected, but maybe more
}
_logger.Info($"Waiting for client to be accepted on port {_listenerProxy.Port}.");
(var readStream, var writeStream, var sourceIP, var sourcePort) = await _listenerProxy.AcceptClient().ConfigureAwait(false);
_logger.Info($"Client accepted on port {_listenerProxy.Port}: IP:{sourceIP}, Port:{sourcePort}");
var clientContext = new ClientContext<TSendMessage, TReceiveMessage>
{
SourceAddress = sourceIP,
SourcePort = sourcePort,
DataAdapter = DataAdapterFactory<TSendMessage, TReceiveMessage>.Create(readStream, writeStream)
};
taskList.Add(HandleClient(clientContext));
}
}
HandleClient 方法定义为:
public async System.Threading.Tasks.Task HandleClient(ClientContext<TSendMessage, TReceiveMessage> clientContext);
我希望能够并行处理最多预定义数量的请求(处理函数是HandleClient)。客户端将连接,发送少量数据,然后关闭连接。
由于整个项目都是异步的,我很想尝试在这部分也使用异步方法。
我很确定不建议使用此解决方案,但我不知道如何以更好的方式完成。我在这里找到了一个非常相关的话题:How to run a Task on a new thread and immediately return to the caller?
Stephen Cleary 在那里发表了评论:
嗯,我建议的第一件事是尝试一个更简单的练习。 说真的,异步 TCP 服务器是最复杂的服务器之一 您可以选择的应用程序。
那么,在这种情况下,“正确”的方法是什么?我知道,我的方法“有效”,但我有一种不好的感觉,尤其是 HandleClient 或多或少是“一劳永逸”。我对生成的任务感兴趣的唯一原因是“限制”吞吐量(最初它是一个异步 void)。事实上,我的问题与链接中的 TO 完全相同。但是,我仍然不知道这种方法的最大问题是什么。
我将不胜感激建设性的提示...谢谢。
【问题讨论】:
-
Codereview 将有助于改进工作代码。
标签: c# sockets asynchronous async-await tcplistener