UDP-клиент использует слишком много памяти при отправке нескольких маленьких частей огромного массива - PullRequest
0 голосов
/ 25 мая 2019

Я захватываю рабочий стол с помощью API Desktop Duplication, кодирую его в h265 и отправляю его частями через UDP (не могу использовать TCP, потому что мне нужна минимальная задержка). Я делаю все это в C # и Visual Studio, и использование памяти идет вверх, как только я раскомментирую udpclient.Send ().

С этим комментарием все прекрасно работает (включая захват кадров, разбиение и т. Д.), Как только я отправляю его, я использую метку 2 ГБ менее чем за 10 секунд, и он продолжает увеличиваться до сбои. Кроме того, ни одна из данных не теряется, так как мой сервер получает все, поэтому управление пакетами мне кажется хорошим.

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 (), который делает все не так. Любая идея о том, что может вызвать это, и как я мог как-то заставить управление памятью с посылкой?

1 Ответ

0 голосов
/ 26 мая 2019

После долгих проб и ошибок "в темноте" мне удалось решить эту проблему, выполнив собственное управление сокетами. Оказывается, разрешено делать как можно больше вызовов «Отправить», но сокет плохо реагирует на него, то есть он все еще пытается отправить, даже если он «забит», и начинает терять память, если это имеет смысл. Я закончил посылку асинхронно и ждал, чтобы узнать, что байты действительно были отправлены, прежде чем предпринять еще одну отправку. Вот код для него, работает отлично, нет утечек памяти, потеря пакетов 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);
    }
...