Pascal-78 Ответов: 2

Как минимизировать потерю пакетов UDP


Привет,

Вот в чем моя проблема:
Я пытаюсь отправить много данных (больших изображений) между 2 ПК с помощью UDP-сокета (UDP-единственный выбор для многоадресной рассылки).

Я использую что-то вроде RUDP (Reliable-UDP), в основном:
- сервер отправляет много UDP-пакетов с идентификатором (по одному на изображение) и индексом пакета
- клиент получает пакеты и восстанавливает изображение с помощью индекса пакета
- если пакеты отсутствуют, клиент отправляет UDP-сообщение серверу для запроса отсутствующих пакетов
- сервер отправляет недостающий пакет
этот цикл действий выполняется до тех пор, пока сервер не должен отправить следующее изображение.

Когда все работает нормально,несколько пакетов отсутствуют, и сеть использует только 5% пропускной способности.
Но иногда почти все пакеты отсутствуют и сеть использует более 25% пропускной способности (ограничение связано с таймаутом в моей реализации, а это работает так, как я хочу) и представляют собой отправку 5 раз одного и того же изображения!

Я пытался :
- деактивация антивируса, брандмауэра
- прямое подключение

- проверка, не сбросила ли Windows Filtering Platform (WFP) какой-то пакет, но при выключенном брандмауэре в журнале ничего не появляется.

- Если я смотрю Монитор ресурсов как на сервере, так и на клиенте, использование сети идентично.

Я знаю, что это должно быть возможно, потому что я могу подключить устройство, отправляющее вдвое большую частоту кадров данных, чем я пробовал, без потери пакетов.

Как я могу исследовать, где пакеты теряются/отбрасываются?

Richard MacCutchan

Переключитесь на TCP.

Pascal-78

А как вы делаете "Многоадресную рассылку" с TCP ?

Homero Rivera

Объясните "многоадресную рассылку". Какова динамика между клиентами и сервером?

TCP определенно может быть "многоадресным".

Как клиенты сигнализируют, что есть изображение, которое нужно получить? Или клиенты просят изображения каждый раз?

Pascal-78

Многоадресная рассылка (http://en.wikipedia.org/wiki/Multicast) - это способ отправки данных (в моем случае) с 1 ПК на многие другие, но не на все.
Одноадресная передача: 1 к 1
Многоадресная рассылка: 1 ко многим, многие ко многим
Трансляция: 1 для всех.

Мой текущий тест сделан только с 2 ПК (1 отправитель, 1 приемник), но основная цель моего проекта будет использовать больше приемников.

Преимущество многоадресной рассылки от TCP: она использовала только 1 отправку для всех клиентов, где TCP нуждается в 1 отправке на каждого клиента. С точки зрения пропускной способности : Многоадресная рассылка не изменяет необходимую пропускную способность, если число клиентов увеличивается, но TCP должен будет использовать N раз большую пропускную способность для N клиентов.

Это приложение похоже на ip-камеру, отправляющую изображения клиентам, клиенты не запрашивают изображение, клиенты прослушивают входящий поток через открытый порт.

Homero Rivera

Я понимаю, что такое многоадресная рассылка в сети :)
Мне интересно, как клиенты узнают, что есть образ, который они должны получить? Или клиенты всегда открыты с помощью сервиса, чтобы получать эти изображения всякий раз, когда сервер отправляет их им?

Разве не было бы проще, если бы у клиентов было приложение с таймером, где каждые несколько минут они проверяли, есть ли на сервере новые изображения? а потом скачать их, если они есть? И загрузка происходила через TCP?

Вот что я имею в виду под динамикой.

Я думаю, что все ваши клиенты используются в качестве серверов. Умно, но, очевидно, вы попали в беду.

Если bandwith-это проблема, то каким должен быть реальный сервер (тот, который предоставляет изображения), который может обслуживать запросы один за другим, а не все сразу, откладывая запросы клиентов до тех пор, пока не наступит их очередь.

Pascal-78

Клиенты опрашивают свой сокет, чтобы проверить, доступны ли новые данные.
Когда данные доступны, они их извлекают.
И да, он похож на сервер, но с вашим предложением он довольно похож:
- клиент отправляет запрос на сервер с помощью TCP
- клиент получает данные с сервера по протоколу TCP
в моем случае нет запроса, отправленного клиентом, и клиент получает данные от сервера с помощью UDP.
Вы говорите о минутах, я-о миллисекундах. на самом деле сервер (тот, который предоставляет изображения) должен отправлять новое изображение каждые 22 МС (примерно 45 img/s), каждое изображение составляет более 2 МБ (и да, это означает более 700 МБ/с, но я использую связь 10 Гб/с между ПК).
А клиенты должны выполнять свою работу в реальном времени. Я не могу задерживать одного клиента...

Homero Rivera

О, я вижу! Вы делаете приложение для прямой передачи. Например, телевизор через интернет или совместное использование рабочего стола или камеры с несколькими пользователями, а?

Так вот в чем дело?

Pascal-78

Это очень хорошая идея,
но для совместного использования рабочего стола несколькими пользователями мы нашли аппаратные решения,
наши камеры уже имеют свой режим многоадресной передачи, но если мы хотим вставить некоторую обработку изображений, мы должны отправить новое изображение с ПК другим или если мы хотим имитировать камеру...

Homero Rivera

Тогда определенно TCP-это не решение; если бы я знал это с самого начала!

Пробовали ли вы какие-либо из этих инструментов для устранения неполадок в вашей сети?
http://blog.pluralsight.com/network-troubleshooting-tools

Как вы думаете, кто-нибудь из них мог бы решить эту проблему для вас?

Pascal-78

Я проверяю ссылку, которую вы дали, но так как я сделал тесты с использованием прямой ссылки, многие инструменты не имеют значения. SpeedTest в локальной сети будет полезен, но не через Интернет...

Homero Rivera

Еще один вопрос... Как ваши клиенты подключаются к потоковому серверу? Это через интернет? Выполняется ли DNS-вызов при каждом отдельном запросе изображения?

И еще одно, Паскаль... Я действительно заинтересован в том, чтобы помочь вам решить эту проблему в меру своих возможностей, даже если это займет у нас несколько дней.
Именно такие проблемы привели меня сюда, они помогают мне взглянуть на вещи, о которых я раньше не думал.
Мне будет приятно продолжать и продолжать заниматься этой проблемой.

Pascal-78

Клиенты подключаются к потоку, регистрируясь в группе многоадресной рассылки (ip-адрес от 224.0.0.0 до 239.255.255.255). Все они используют один и тот же адрес многоадресной рассылки, и сервер отправляет изображения на этот адрес многоадресной рассылки.
Когда я использую только 1 клиент, клиент не регистрируется в группе многоадресной рассылки, и сервер отправляет изображения непосредственно на ip-адрес клиента.
У меня есть реальный TCP/IP-сервер, работающий для настройки отправителя изображения от клиента или для получения группы многоадресной рассылки от нового клиента.

Любая помощь будет оценена по достоинству. Я работаю над этим уже несколько недель. Это будет хорошая статья, если мы успешно решим эту проблему.

Homero Rivera

Эта статья показывает обещание как структурированный способ устранения неполадок сети и пакетов ( https://documentation.meraki.com/zGeneral_Administration/Tools_and_Troubleshooting/Troubleshooting_packet_loss_between_devices ).

Может быть, вы использовали пинги и тому подобные вещи, но я не знал, что раньше вы могли увеличить количество пакетов, отправляемых миллионами!
Таким образом, если вы попробуете 1000 пакетов и не получите никакой существенной потери пакетов, то у вас, вероятно, нет проблем с сетью.

Тогда статья становится более интересной, потому что если вы действительно получаете огромную потерю пакетов, вы можете использовать tracert, чтобы изолировать точку, где происходит потеря.

Нет необходимости в причудливых инструментах, просто старая Командная строка.

Вы уже пробовали все это?

Pascal-78

Я попробовал ping с опцией-t для непрерывного тестирования, и ни один пакет не теряется при ping, но в то же время моя программа все еще теряет пакеты.
И если вы используете ping с -n 1000, вам придется ждать 1000 секунд, чтобы получить результат. пинг делает запрос каждую секунду.
Я совершенно уверен, что проблема не в сети, а в IP-стеке Windows, или в платформе фильтрации Windows, или в самой моей программе...

Я нашел эту программу: https://iperf.fr/
и его результаты аналогичны моей программе, где-то 88% потерь дейтаграмм, где-то 0%...

2 Ответов

Рейтинг:
20

Pascal-78

Решение было слишком простым:

увеличьте параметр сокета ReCeiVe BUFfer (также называемый SO_RCVBUF).

по умолчанию этот буфер равен 8 Кб, в моем случае это размер одного UDP-пакета. Это означает, что когда мой клиент читает пакет, это должно быть сделано до того, как сервер отправит новый пакет, или новый пакет будет отброшен IP-стеком.

Я увеличил буфер до большего значения (в два раза больше размера изображения), используя setsockopt функция:

int rcvbufsize = myBigImageSize*2;
setsockopt(mySocket,SOL_SOCKET,SO_RCVBUF,(char*)&rcvbufsize,sizeof(rcvbufsize));


Я увеличил скорость своего сервера (за счет меньшего ожидания между каждым пакетом) и никакой потери пакетов!

Теперь мне нужно оптимизировать размер этого приемного буфера.


Рейтинг:
0

Javier Luis Lopez

У меня есть аналогичная проблема, но я могу снимать изображения с потерянными пакетами.
Я решил эту проблему, сделав следующие шаги:
1. Увеличение сокета размер буфера как сказал Паскаль-78
2. в приемной части я сделал отдельный поток, который принимает только пакеты
3. поддерживайте связь в прямом эфире, посылая обратно команду подтверждения каждый раз, когда я получаю команду
4. Использование select () с таймаутом от 10 до 500 микросекунд для поиска пакета перед его чтением
5. Как мой soultion должны также работать в Linux я сделал следующую команду, чтобы разрешить увеличить размер патрона :

sudo sysctl -w net.core.rmem_max=myMaxImagesize*2

6.я писал на консоли сообщение каждый раз, когда поступали данные, но, к сожалению, windows провоцирует большую задержку записи на консоли. Я решил это, написав эти строки кода в начале main (), чтобы увеличить консольный буфер:
#ifndef __linux__   //Introduce this code at the beginning of main() to increase a lot the speed of cout in windows: 
	char buf[4000]; setvbuf(stdout, buf, _IOFBF, sizeof buf);
#endif