2010-07-19 53 views
2

我有一个简单的.net 3.5sp1窗口应用程序(在C#中)充当UDP服务器。它监听端口,接收来自端点的数据,然后将接收到的数据重新发送到另一个端点(即中继,用于实况广播数据流)。我所经历的是在连接达到约20分钟后,它开始恶化。另外我注意到它每秒吞噬大约50-100K的内存,这在GC之后从未得到释放。我必须关闭应用程序并重新启动它。不好。我已经缩小的问题下面的代码,它不重传向另一侧:SendToAsync内存泄漏?

var sendBuffer = new byte[readCount]; 
Array.Copy(readData, sendBuffer, readCount); 
SocketAsyncEventArgs args = new SocketAsyncEventArgs(); 
args.RemoteEndPoint = p.EP; 
args.SetBuffer(sendBuffer, 0, sendBuffer.Length); 
SwitchWindow.LineSocket.SendToAsync(args); 

有没有人有与SendToAsync内存泄漏的经验吗?

UPDATE:

我实例化时,插座被初始化的状态对象(仅做一次)。状态对象有一个名为“缓冲区”的属性,它是一个字节数组。我收到的数据异步从插座像这样:

private void beginReceiveData(ref MessageState state) 
{ 
    var ipeSender = new IPEndPoint(IPAddress.Any, 0); 
    var epSender = (EndPoint)ipeSender; 

    state.workSocket = LineSocket; 
    state.EP = epSender; 
    state.workSocket.BeginReceiveFrom(state.buffer, 0, MessageState.BufferSize, 
     SocketFlags.None, ref epSender, 
     new AsyncCallback(ReceiveDataCB), 
     state); 
} 

而且,然后在我的回调(ReceiveDataCB),我检索异步对象,然后传递字节的缓冲区给另一个函数进行处理,进而调用上面发布的代码重传到另一端(state.buffer成为readData)。

更新#2:

继我的直觉,我改变了发送代码到下面,除暴安良的SocketAsyncEventArgs和SendToAsync的:

var sendBuffer = new byte[readCount]; 
Array.Copy(readData, sendBuffer, readCount); 
SwitchWindow.LineSocket.BeginSendTo(
    sendBuffer, 0, sendBuffer.Length, SocketFlags.None, 
    p.EP, new AsyncCallback(echoCB), null); 

,当然,我说的“ echoCB“回调除了调用EndSendTo之外什么也不做。内存泄漏现在消失了!我怀疑这与创建如此多的SocketAsyncEventArgs对象有关,而异步函数挂在这些对象上,每个数据包一个(每秒33个数据包,可以快速加起来)。我再次查看了SocketAsyncEventArgs的MSDN文档,并注意到在服务器提供的“示例”代码中,他们使用了一组SocketAsyncEventArgs对象。我认为它的设计并不像我使用它的方式一样。我认为整个过程不必为每个调用实例化这些缓冲区等,因此可以重用它们并使服务器获得更好的性能。

回答

0

readData缓冲区在哪里分配?
整个收/发环路是否在同一个范围内?

+0

看到我的修改我贴 – 2010-07-19 18:32:47

0

您可以随时使用

!gcroot <address> 

追查谁是保持你的对象的引用。请参阅CLR Memory Leak

0

我认为你的中继节点在接收数据方面做了很多工作,并最终以比发送数据更快的速度接收数据。当数据从网络中传出时,您正在为它分配内存并排队等待发送异步样式,但是您的外发数据可能比您接收(并分配)新数据的速度慢得多,导致传入数据。在下载速度高于上传速度的网络节点上通常会出现这种情况。

您可以节制接受和分配的传入数据量。您可以使用回拨来执行此操作(参数。完成)通过跟踪排队发送的数据量与实际发送的数据量(通过在回调中发送的跟踪)。如果等待发送的数据量大于某个任意限制,请不要接受新数据。

如果你在做流式视频,你可能不得不跳过帧或丢弃整个数据包。

+0

好想法。我正在做流式音频,但它不会落后或跳过。实际上,我正在监视bytes/in/out和它们是相同的。由于传输,我能够保持大约1/3秒的延迟。 – 2010-07-19 18:36:04

5

您可能不会打电话给SocketAsyncEventArgs.Dispose()