gpt4 book ai didi

c# - TcpListener 与 SocketAsyncEventArgs

转载 作者:行者123 更新时间:2023-11-30 12:26:39 26 4
gpt4 key购买 nike

是否有正当理由不使用 TcpListener 而不是 SocketAsyncEventArgs 来实现高性能/高吞吐量 TCP 服务器?

我已经使用 SocketAsyncEventArgs 实现了这个高性能/高吞吐量的 TCP 服务器,经历了各种令人头疼的问题,使用一个大的预分配 byte 来处理这些固定缓冲区SocketAsyncEventArgs 的数组和池用于接受和接收,使用一些低级的东西和 Shiny 的智能代码与一些 TPL 数据流和一些 Rx 放在一起,它完美地工作;在这方面的努力几乎是教科书 - 实际上,我从其他人的代码中学到了超过 80% 的这些东西。

但是也存在一些问题和顾虑:

  1. 复杂性:我不能将对此服务器的任何类型的修改委托(delegate)给另一个服务器团队成员。这使我不得不从事这类任务,我可以对其他项目的其他部分关注不够。
  2. 内存使用情况(固定byte 数组):使用SocketAsyncEventArgs 需要池来被预先分配。所以要处理 100000 个并发连接(更糟糕的情况,即使在不同的端口上)一大堆 RAM 无用地盘旋在那里;预先分配(即使只是在某些时候满足这些条件,服务器应该能够每天处理 1 或 2 个这样的高峰。
  3. TcpListener 实际上运行良好:我实际上已经将 TcpListener 放入测试中(使用一些技巧,例如在专用线程上使用 AcceptTcpClient不是 async版本,然后将接受的连接发送到ConcurrentQueue 而不是就地创建 Task 等等)使用最新版本的 .NET,它运行良好,几乎一样好作为 SocketAsyncEventArgs,没有数据丢失和低内存占用这有助于避免在服务器上浪费太多 RAM,并且不需要预先分配。

那么,为什么我没有看到任何地方使用 TcpListener 而每个人(包括我自己)都在使用 SocketAsyncEventArgs?我错过了什么吗?

最佳答案

我没有看到任何证据表明这个问题是关于 TcpListener 的。您似乎只关心处理已被接受的连接的代码。这样的连接独立于监听器。

SocketAsyncEventArgs 是一种 CPU 负载优化。我相信您可以使用它实现更高的每秒操作率。与普通 APM/TAP 异步 IO 的区别有多大?肯定小于一个数量级。大概在 1.2 倍到 3 倍之间。上次我对环回 TCP 事务率进行基准测试时,我发现内核占用了大约一半的 CPU 使用率。这意味着通过无限优化,您的应用最多可以提高 2 倍的速度。

请记住,SocketAsyncEventArgs 是在 2000 年左右被添加到 BCL 中的,当时 CPU 的能力要差得多。

仅当您有证据表明需要它时才使用 SocketAsyncEventArgs。它会使您的工作效率大大降低。更多错误的可能性。

这是套接字处理循环的模板:

while (ConnectionEstablished()) {
var someData = await ReadFromSocketAsync(socket);
await ProcessDataAsync(someData);
}

非常简单的代码。由于 await,没有回调。


如果您担心托管堆碎片:在启动时分配一个 new byte[1024 * 1024]。当你想从套接字读取一个字节到这个缓冲区的某个空闲部分时。当单字节读取完成时,您询问实际有多少字节 (Socket.Available) 并同步提取其余字节。这样,您只需固定一个相当小的缓冲区,并且仍然可以使用异步 IO 来等待数据到达。

此技术不需要轮询。由于 Socket.Available 只能增加而不从套接字读取,因此我们不会冒意外执行太小的读取的风险。

或者,您可以通过分配一些非常大的缓冲区并分发 block 来对抗托管堆碎片。

或者,如果您认为这不是问题,则无需执行任何操作。

关于c# - TcpListener 与 SocketAsyncEventArgs,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27755330/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com