Как увеличить скорость передачи данных при использовании UDP? - PullRequest
0 голосов
/ 23 апреля 2019

Я начал работать над собственным проектом, который я делаю для развлечения. Я создал приложение, которое использует дырокол UDP и затем передает данные с одного устройства A на второе устройство B, и я пытаюсь найти способ оптимизации скорости передачи.

Изначально у меня были некоторые проблемы с инициализацией передачи данных и получением данных на стороне получателя при выполнении тестов через Интернет и различные сети. После исследования я в конечном итоге уменьшил данные каждого пакета до 504 байтов, чтобы полезная нагрузка пакетов была ниже 508 байтов, что является максимальной безопасной полезной нагрузкой UDP . Это решило множество проблем, которые, по моему мнению, были вызваны потерей пакетов, и почти все время, когда я тестировал его с этой конфигурацией, работало идеально (при повторной передаче потерянных пакетов).

Передаваемые данные могут различаться по размеру (от нескольких КБ до 100 МБ), и когда передача инициируется, я беру исходные данные, обрабатываю их и делю их на пронумерованные куски по 504 байта и запускаю их через DatagramSocket отправителя. У меня есть цикл, который циклически перебирает пакеты, которые не были получены получателем, и отправитель поддерживает этот цикл в течение приличного количества попыток или времени, пока передача не будет успешно завершена или с ошибкой. В то же время отправитель прослушивает те же DatagramSocket для пакетов подтверждения, которые приходят от получателя. Получатель на другом конце (после какого-то рукопожатия, который получает информацию о том, сколько пакетов будет следовать) постоянно прослушивает входящие пакеты, и всякий раз, когда он получает один, он немедленно запускает пакет подтверждения.

Это прекрасно работает, но может быть очень медленным в зависимости от потери пакетов при каждой передаче (например, 20 минут для файла 5 МБ было одним из худших времен или 30-40 секунд для файла 5 МБ).

Ниже вы можете увидеть некоторый псевдокод, но с важными частями реализации:

//Sender side:
packetsToSend = ArrayList<ByteArray>()
keepTransfering = true
while(packetsToSend.isNotEmpty() && keepTransfering) {
   packetsToSend.forEach { packet ->
      datagramSocket.send( DatagramPacketCreation(packet) )
      ackPacket = datagramSocket.receive(TIMEOUT=1) //1 millisecond timeout
      processAckPacket(ackPacket)
   }
}

С вышеописанным циклом и существующими потерями пакетов мне удалось получить скорость, равную 30-40 секундам, что составляет около 128 КБ / с.

Несколько недель назад я думал перенести часть получения подтверждения в другую ветку, чтобы это ускорило процесс. Протестировал его локально, работал нормально. Затем попытался проверить его через Интернет, и , по-видимому, маршрутизатор не может справиться с этим из-за перегрузки таблицы маршрутизатора .

Что я могу улучшить в логике, чтобы увеличить скорость без перегрузки маршрутизатора? Если у меня 1 миллисекундное ожидание (даже без получения пакета - давайте предположим, что я делаю это в другом потоке), скорость все равно будет ограничена до 488 КБ / с (5000 байт / с). Как бы я достиг более высоких скоростей, таких как 2-3 МБ / с?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...