Asynchronouos Socket Communication&堆碎片

时间:2013-11-14 05:20:32

标签: sockets heap async-await asyncsocket

我编写了一个多线程Socket Server应用程序,它接受超过1000个并发连接。最近我们有应用程序崩溃;在分析了转储文件之后,知道应用程序因堆损坏而崩溃。我发现在以下链接中讨论了同样的问题。

.NET Does NOT Have Reliable Asynchronouos Socket Communication? http://support.microsoft.com/kb/947862

并且讨论也提出了3种解决方案。

  1. 网络应用程序应该对其发布的未完成异步IO的数量设置上限。

  2. 使用Microsoft CCR

  3. 使用TPL

  4. 由于时间因素,我认为坚持#1,但我没有清楚的图片如何实现这一点。有人能给出一个好的起点吗?

    还有没有人使用Async与TPL解决这个问题?

2 个答案:

答案 0 :(得分:1)

你的意思是比你所指的答案中的blog posting that I linked to更好的起点?

问题在于:

  • 在异步写入期间使用的内存和其他每个操作资源通常“正在使用”,直到远程对等方的TCP堆栈响应数据并且本地堆栈可以完成异步写入操作以告诉您可以重用缓冲液中。
  • 本地对等方无法控制它,因为它全部由远程对等方从其套接字读取数据的速度以及两个对等方之间链路的拥塞来控制。

由于上述原因,您需要对任何时候未完成的异步写入量进行硬性限制。您可以通过在发出异步写入之前递增计数器并在完成处理程序中将其递减来跟踪它。

一旦达到这个限制,你所做的就由你决定。在原始文章中,我赞成将要写入的数据放入的队列。然后,当发生写入完成时,该队列可以用作数据源。队列为空后,您可以再次正常发送。当然这只会移动问题 - 你仍然有一个由远程对等体(排队数据)控制的内存资源,但你也没有使用其他操作系统资源(非页面缓冲池,I / O页锁定限制,等)。

您可以在达到限制时停止对等发送 - 现在,您通过异步API构建的API需要具有“此时无法发送,稍后再试”从之前的发送返回以前总是“工作”。

如果您这样做,我还会认真考虑通过在一个连续的块中分配大块缓冲区并在池中使用它们来避免固定内存问题。

答案 1 :(得分:0)

首先,这是一篇非常古老的知识库文章。您如何确定 特定问题? 然后,正如Hans Passant在SO问题中回答的那样,如果你编写了错误的异步代码,它咬你。如果你不处理你的资源(并且内存缓冲区是资源),并发程序面临内存错误

使用原始线程编写好的并发代码非常困难,而TPL确实使其更容易,但它无法修复您已有的错误。实际上,除非您确定当前的问题,否则您可能会将它们转移到使用TPL的版本。

在不知道导致应用程序崩溃的具体问题的情况下,我只能提出一些建议:

  1. 使用BufferManager重用内存缓冲区而不是分配新缓冲区。
  2. 使用队列来存储请求并异步处理它们,而不是为每个请求启动新线程。
  3. 您还可以使用其他技术,具体取决于您正在构建的应用程序类型。例如,您可以使用TPL DataFlow以独立的步骤中断处理。

    至于CCR,在Robotics Studio之外使用它没什么意义。 TPL包含编写并发应用程序所需的大部分相关功能。