TcpListener 与 SocketAsyncEventArgs

2023-12-08

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

我已经使用以下方法实现了这个高性能/高吞吐量 TCP 服务器SocketAsyncEventArgs使用大的预分配的处理这些固定缓冲区经历了各种令人头痛的事情byte数组和池SocketAsyncEventArgs对于接受和接收,使用一些低级的东西和闪亮的智能代码与一些 TPL 数据流和一些 Rx 组合在一起,它工作得很好;这方面的工作几乎是教科书——实际上,我从其他人的代码中学到了 80% 以上的内容。

但也存在一些问题和担忧:

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

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


我没有看到任何证据表明这个问题是关于TcpListener根本不。看来您只关心处理已被接受的连接的代码。这种连接独立于侦听器。

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

请记住SocketAsyncEventArgs大约在 2000 年左右被添加到 BCL,当时 CPU 的能力还远远不够。

Use SocketAsyncEventArgs仅当您有证据表明您需要它时。它会导致你的工作效率大大降低。更容易出现错误。

这是您的套接字处理循环应如下所示的模板:

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

非常简单的代码。没有回调,感谢await.


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

该技术不需要轮询。自从Socket.Available只可以increase如果不从套接字读取,我们就不会冒意外执行太小的读取的风险。

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

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

TcpListener 与 SocketAsyncEventArgs 的相关文章

  • 属性对象什么时候创建?

    由于属性实际上只是附加到程序集的元数据 这是否意味着属性对象仅根据请求创建 例如当您调用 GetCustomAttributes 时 或者它们是在创建对象时创建的 或者 前两个的组合 在由于 CLR 的属性扫描而创建对象时创建 从 CLR
  • 自动从 C# 代码进行调试过程并读取寄存器值

    我正在寻找一种方法来读取某个地址的 edx 注册表 就像这个问题中所问的那样 读取eax寄存器 https stackoverflow com questions 16490906 read eax register 虽然我的解决方案需要用
  • Signalr 在生产服务器中总是陷入长轮询

    当我在服务器中托管应用程序时 它会检查服务器端事件并始终回退到长轮询 服务器托管环境为Windows Server 2012 R1和IIS 7 5 无论如何 我们是否可以解决这个问题 https cloud githubuserconten
  • 如何在C++中实现模板类协变?

    是否可以以这样一种方式实现类模板 如果模板参数相关 一个对象可以转换为另一个对象 这是一个展示这个想法的例子 当然它不会编译 struct Base struct Derived Base template
  • 嵌入式系统中的malloc [重复]

    这个问题在这里已经有答案了 我正在使用嵌入式系统 该应用程序在 AT91SAMxxxx 和 cortex m3 lpc17xxx 上运行 我正在研究动态内存分配 因为它会极大地改变应用程序的外观 并给我更多的力量 我认为我唯一真正的路线是为
  • fgets() 和 Ctrl+D,三次才能结束?

    I don t understand why I need press Ctrl D for three times to send the EOF In addition if I press Enter then it only too
  • SSH 主机密钥指纹与模式 C# WinSCP 不匹配

    我尝试通过 WinSCP 使用 C 连接到 FTPS 服务器 但收到此错误 SSH 主机密钥指纹 与模式不匹配 经过大量研究 我相信这与密钥的长度有关 当使用 服务器和协议信息 下的界面进行连接时 我从 WinSCP 获得的密钥是xx xx
  • 如何在 WPF RichTextBox 中跟踪 TextPointer?

    我正在尝试了解 WPF RichTextBox 中的 TextPointer 类 我希望能够跟踪它们 以便我可以将信息与文本中的区域相关联 我目前正在使用一个非常简单的示例来尝试弄清楚发生了什么 在 PreviewKeyDown 事件中 我
  • C# 用数组封送结构体

    假设我有一个类似于 public struct MyStruct public float a 我想用一些自定义数组大小实例化一个这样的结构 在本例中假设为 2 然后我将其封送到字节数组中 MyStruct s new MyStruct s
  • HttpClient 像浏览器一样请求

    当我通过 HttpClient 类调用网站 www livescore com 时 我总是收到错误 500 可能服务器阻止了来自 HttpClient 的请求 1 还有其他方法可以从网页获取html吗 2 如何设置标题来获取html内容 当
  • 基于范围的 for 循环中的未命名循环变量?

    有没有什么方法可以不在基于范围的 for 循环中 使用 循环变量 同时也避免编译器发出有关未使用它的警告 对于上下文 我正在尝试执行以下操作 我启用了 将警告视为错误 并且我不想进行像通过在某处毫无意义地提及变量来强制 使用 变量这样的黑客
  • 按字典顺序对整数数组进行排序 C++

    我想按字典顺序对一个大整数数组 例如 100 万个元素 进行排序 Example input 100 21 22 99 1 927 sorted 1 100 21 22 927 99 我用最简单的方法做到了 将所有数字转换为字符串 非常昂贵
  • 使用安全函数在 C 中将字符串添加到字符串

    我想将文件名复制到字符串并附加 cpt 但我无法使用安全函数 strcat s 来做到这一点 错误 字符串不是空终止的 我确实设置了 0 如何使用安全函数修复此问题 size strlen locatie size nieuw char m
  • 如何在 Team Foundation 上强制发表有意义的签入评论?

    我有一个开发团队有一个坏习惯 他们写道poor签入评论 当我们必须在团队基础上查看文件的历史记录时 这使得它成为一场噩梦 我已经启用了变更集评论政策 这样他们甚至可以在签到时留下评论 否则他们不会 我们就团队的工作质量进行了一些讨论 他们很
  • 用 C 实现 Unix shell:检查文件是否可执行

    我正在努力用 C 语言实现 Unix shell 目前正在处理相对路径的问题 特别是在输入命令时 现在 我每次都必须输入可执行文件的完整路径 而我宁愿简单地输入 ls 或 cat 我已经设法获取 PATH 环境变量 我的想法是在 字符处拆分
  • C 中的位移位

    如果与有符号整数对应的位模式右移 则 1 vacant bit will be filled by the sign bit 2 vacant bit will be filled by 0 3 The outcome is impleme
  • 方法参数内的变量赋值

    我刚刚发现 通过发现错误 你可以这样做 string s 3 int i int TryParse s hello out i returns false 使用赋值的返回值是否合法 Obviously i is but is this th
  • 如何使用 ReactiveList 以便在添加新项目时更新 UI

    我正在创建一个带有列表的 Xamarin Forms 应用程序 itemSource 是一个reactiveList 但是 向列表添加新项目不会更新 UI 这样做的正确方法是什么 列表定义 listView new ListView var
  • C++ 成员函数中的“if (!this)”有多糟糕?

    如果我遇到旧代码if this return 在应用程序中 这种风险有多严重 它是一个危险的定时炸弹 需要立即在应用程序范围内进行搜索和销毁工作 还是更像是一种可以悄悄留在原处的代码气味 我不打算writing当然 执行此操作的代码 相反
  • 为什么 strtok 会导致分段错误?

    为什么下面的代码给出了Seg 最后一行有问题吗 char m ReadName printf nRead String s n m Writes OK char token token strtok m 如前所述 读取字符串打印没有问题 但

随机推荐