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 的相关文章

  • 具有不同大小结构的结构数组的 malloc()

    如果每个结构都包含一个大小不同的字符串数组 那么如何正确地 malloc 一个结构数组 因此每个结构可能有不同的大小 并且不可能 realloc 结构体数量 sizeof 结构体名称 after malloc 初始大小 sizeof 结构名
  • clang 格式换行符在错误的位置

    给出以下代码行 get abc manager get platform status abc platform status sw update status fill update status actions allowed stat
  • C 程序从连接到系统的 USB 设备读取数据

    我正在尝试从连接到系统 USB 端口的 USB 设备 例如随身碟 获取数据 在这里 我可以打开设备文件并读取一些随机原始数据 但我想获取像 minicom teraterm 这样的数据 请让我知道我可以使用哪些方法和库来成功完成此操作以及如
  • 如何尝试/捕获所有异常

    我正在完成由其他人启动的 UWP 应用程序 该应用程序经常崩溃 我总是陷入困境应用程序 at if global System Diagnostics Debugger IsAttached global System Diagnostic
  • C++中delete和delete[]的区别[重复]

    这个问题在这里已经有答案了 可能的重复 C 中的删除与删除 运算符 https stackoverflow com questions 2425728 delete vs delete operators in c 我写了一个包含两个指针的
  • 选择列表逻辑应位于 ASP.NET MVC、视图、模型或控制器中的什么位置?

    我觉得我的问题与这个问题很接近 但我想对这样的代码应该放在哪里进行更一般的讨论 Asp Net MVC SelectList 重构问题 https stackoverflow com questions 2149855 asp net mv
  • 如何创建用于 QML 的通用对象模型?

    我想知道是否有任何宏或方法如何将 Qt 模型注册为 QObject 的属性 例如 我有AnimalModel http doc qt io qt 5 qtquick modelviewsdata cppmodels html qabstra
  • 从 Code::Blocks 运行程序时出现空白控制台窗口 [重复]

    这个问题在这里已经有答案了 当我尝试在 Code Blocks 中构建并运行新程序时 控制台窗口弹出空白 我必须单击退出按钮才能停止它 它对我尝试过的任何新项目 包括 Hello world 都执行此操作 奇怪的是 它对于我拥有的任何旧项目
  • 从成员函数指针类型生成函子

    我正在尝试简化 通过make fn 预处理参数的函子的生成 通过wrap 对于 arity 的成员函数n 生成函子基本上可以工作 但到目前为止只能通过显式指定成员函数的参数类型来实现 现在我想从它处理的成员函数类型生成正确的函子 struc
  • 预处理后解析 C++ 源文件

    我正在尝试分析c 使用我定制的解析器的文件 写在c 在开始解析之前 我想摆脱所有 define 我希望源文件在预处理后可以编译 所以最好的方法是运行C Preprocessor在文件上 cpp myfile cpp temp cpp or
  • 使用 WF 的多线程应用程序的错误处理模式?

    我正在写一个又长又详细的问题 但只是放弃了它 转而选择一个更简单的问题 但我在这里找不到答案 应用程序简要说明 我有一个 WPF 应用程序 它生成多个线程 每个线程执行自己的 WF 处理线程和 WF 中的错误 允许用户从 GUI 端进行交互
  • 如何随着分辨率的变化自动调整大小和调整表单控件

    我注意到某些应用程序会更改控件的位置以尽可能适应当前的分辨率 例如 如果窗口最大化 则控件的设置方式应使整个 GUI 看起来平衡 是否可以使用 C 在 Visual studio 2010 中制作或实现此功能 Use Dock http m
  • 二叉树中的 BFS

    我正在尝试编写二叉树中广度优先搜索的代码 我已将所有数据存储在队列中 但我不知道如何访问所有节点并消耗它们的所有子节点 这是我的 C 代码 void breadthFirstSearch btree bt queue q if bt NUL
  • .NET 客户端中 Google 表格中的条件格式请求

    我知道如何在 Google Sheets API 中对值和其他格式进行批量电子表格更新请求 但条件格式似乎有所不同 我已正确设置请求 AddConditionalFormatRuleRequest formatRequest new Add
  • DataTable:通过 LINQ 或 LAMBDA 进行动态 Group By 表达式

    我有一个数据表 我想在其中对未指定数量的字段进行分组 发生这种情况的原因是用户可以选择他想要分组的字段 所以 实际上 我将选择推入列表中 在这个选择上 我必须对我的数据表进行分组 想象一下这段代码 VB 或 C 都一样 public voi
  • 初始化 LPCTSTR /LPCWSTR [重复]

    这个问题在这里已经有答案了 我很难理解并使其正常工作 基本上归结为我无法成功初始化这种类型的变量 它需要有说的内容7 2E25DC9D 0 USB003 有人可以解释 展示这种类型的正确初始化和类似的值吗 我已查看此站点上的所有帮助 将项目
  • 在 C++17 中使用 成员的链接错误

    我在 Ubuntu 16 04 上使用 gcc 7 2 并且需要使用 C 17 中的新文件系统库 尽管确实有一个名为experimental filesystem的库 但我无法使用它的任何成员 例如 当我尝试编译此文件时 include
  • 如何查找连接到 AF_INET 套接字的客户端的 UID?

    有什么方法或类似的东西ucred for AF UNIX如果是AF INET插座 TCP在我的例子中 找出连接到我的套接字的客户端的UID 还有 proc net tcp但它显示了UID of the creator插座的而不是连接的cli
  • 为什么文件更新时“如果较新则复制”不复制文件?

    我在 Visual Studio Express 中有一个解决方案 如下所示 The LogicSchemaC 中的类 将在运行时解析指定的 XML 文件 以下是在main的方法Program cs LogicSchema ls new L
  • 在 Xamarin 中获取 OutOfMemoryException

    java lang OutOfMemoryError 考虑增加 JavaMaximumHeapSize Java 执行时内存不足 java exe 我的 Visualstudio Xamarin 项目出现内存不足异常 请帮助我如何解决此问题

随机推荐