Как отправить большие данные с помощью C # UdpClient? - PullRequest
8 голосов
/ 23 февраля 2010

Я пытаюсь отправить большой объем данных (более 50 МБ) с помощью C # UdpClient.

Итак, сначала я разбил данные на блоки по 65507 байт и отправил их в цикле.

for(int i = 0; i < packetCount; i++)
   myUdpClient.Send(blocks[i], block[i].Length, remoteEndPoint);

Моя проблема в том, что могут быть получены только первые пакеты. Во время отправки первого пакета нагрузка на сеть быстро увеличивается до 100%, а затем другие пакеты не могут быть получены.

Я хочу получить максимально возможную пропускную способность.

Извините за мой английский! Заранее спасибо за помощь.

Ответы [ 4 ]

10 голосов
/ 07 августа 2010

Для всех тех людей, которые говорят, что используют TCP .... глупо неправильно. Хотя протокол TCP надежен и окно, поддерживаемое ядром, является протоколом «установил и забыл», но когда дело доходит до парня, желающего использовать 100% своей пропускной способности, TCP не подойдет (он слишком сильно душит, и ожидание ACK автоматически помещает как минимум 50% мусора из-за RTT).

К первоначальному вопросу, вы отправляете UDP-пакеты без остановки в этом цикле for, окно заполняется, а затем любые новые данные удаляются немедленно и даже не пытаются выйти на линию. Вы также разделяете свои данные слишком большими. Я бы порекомендовал создать свой собственный механизм дроссельной заслонки, который начинается с 2 тыс. Сегментов в секунду и медленно развивается. Каждый «сегмент» содержит SEQ (идентификатор последовательности для подтверждений или ACK) и OFF (смещение внутри файла для этого набора данных). Поскольку данные помечаются, пусть сервер отслеживает эти теги. Когда другая сторона получает их, она сохраняет номера SEQ в списке ACK, и все отсутствующие номера SEQ помещаются в список таймера NACK, когда таймер заканчивается (если они не были получены), он перемещается в список NACK. , Приемник должен отправлять около 5 ACK из списка ACK вместе с 5 NACK в одной передаче каждые пару секунд или около того. Если отправитель получает эти сообщения и имеются какие-либо NACK, он должен немедленно уменьшить скорость и повторно отправить отсутствующий фрагмент, прежде чем продолжить. Данные, которые подтверждены ACK, могут быть освобождены из памяти.

Удачи!

2 голосов
/ 23 февраля 2010

Я не знаю конкретно о реализации .Net, это может быть буферизация ваших данных, но датаграмма UDP обычно ограничена MTU канала, который равен 1500 в обычной сети Ethernet (вычтите 20 байтов для заголовка IP и 8 байтов UDP заголовок.)

UDP явно разрешено отбрасывать и переупорядочивать дейтаграммы, а управление потоками отсутствует, как в TCP.

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

Edit:

Я бы настоятельно рекомендовал использовать TCP для передачи больших файлов. TCP обеспечивает последовательность (вам не нужно отслеживать пропущенные и переупорядоченные пакеты). Он имеет расширенное управление потоком (поэтому быстрый отправитель не перегружает медленного получателя). Он также выполняет обнаружение Path MTU (то есть находит оптимальный пакетирования данных и позволяет избежать фрагментации IP-адресов.) В противном случае вам придется самостоятельно реализовать большинство этих функций.

2 голосов
/ 23 февраля 2010

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

0 голосов
/ 23 февраля 2010

Надежно - нет, вы не будете делать это с UDP.

Насколько я понимаю, это имеет смысл для одновременной отправки на несколько компьютеров (трансляция).

В этом случае

  • установить TCP-соединение с каждым из них,
  • разбить данные на блоки,
  • присвоить каждому блоку идентификатор,
  • отправить список идентификаторов на каждый компьютер с TCP-соединением,
  • широковещательные данные с UDP,
  • информировать клиентов (через TCP), что передача данных завершена,
  • чем клиенты должны запросить повторную отправку отброшенных пакетов
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...