首页 > 解决方案 > UDP 客户端在发送一个巨大数组的多个小部分时使用了太多内存

问题描述

我正在使用 Desktop Duplication API 捕获桌面,将其编码为 h265 并通过 UDP 部分发送(不能使用 TCP,因为我需要尽可能低的延迟)。我在 C# 和 Visual Studio 中完成所有这些工作,一旦我取消注释 udpclient.Send(),内存使用量就会飙升。

有了它的评论,一切都很好(包括帧捕获、分割等),一旦我发送它,我在不到 10 秒的时间内就达到了 2gb 的使用量,并且它一直在增加直到它崩溃。此外,当我的服务器接收所有数据时,没有任何数据丢失,因此我的数据包管理似乎很好。

int offset = 0;
int packetSize = 200;
for (int i=0; i< clone.Length/packetSize; i++)
{
   int diff = clone.Length - offset;
   if (diff > packetSize)
      Array.ConstrainedCopy(clone, offset, subBuffer, 0, packetSize);
   else
      Array.ConstrainedCopy(clone, offset, subBuffer, 0, diff);
   udpClient.Send( subBuffer, packetSize, "255.255.255.255", 9009);
   offset += packetSize;
}

我在这个阶段只是在尝试分裂和一切,正如所说的那样,这部分都不会产生任何问题(我知道它可以做得更好)。只是 udpclient.Send() 让一切都出错了。关于可能导致这种情况的任何想法以及我如何以某种方式通过发送强制进行一些内存管理?

标签: c#visual-studionetworkingudpclient

解决方案


在“在黑暗中”进行大量试验和错误之后,我设法通过自己的套接字管理来解决它。事实证明,允许尽可能多的“发送”调用,但套接字对它的响应不佳,这意味着即使它“阻塞”它仍然会尝试发送,并且如果这有意义,它就会开始泄漏内存。我最终异步发送并等待知道字节是否真的发送,然后再尝试另一次发送。这是它的代码,完美运行,没有内存泄漏,0丢包。我从从这里获取的简单套接字实现开始,然后添加了自定义管理部分。

    Boolean isAvailable = true;
    public void Send(byte[] data)
    {
            if (!isAvailable)
                return;
            isAvailable = false;
        _socket.BeginSend(data, 0, data.Length, SocketFlags.None, (ar) =>
        {     
            _socket.EndSend(ar);
            isAvailable = true;
        }, state);
    }

推荐阅读