2009-05-20 6 views
4

У меня создалось впечатление, что неустойчивость UDP является свойством физического уровня, но кажется, что это не так:«Правильный» способ отправки последовательности дейтаграмм UDP?

Я пытаюсь отправить сообщение через UDP, который разделен на последовательность пакетов , Идентификация сообщения и повторный заказ выполняются неявно.

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

Теперь факт, что потери происходят даже на одной машине, заставляет меня удивляться, что я делаю это правильно?

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

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

Если я добавил паузу (Sleep (...)) между точками, она работает на 100%.

EDIT: Как следует из ответов: пакеты просто отправляются слишком быстро, а ОС выполняет минимальную буферизацию. Это логично.

Итак, если я хотел бы предотвратить добавление подтверждения и повторной передачи в систему (я мог бы просто использовать TCP тогда), что мне делать? Каков наилучший способ улучшить коэффициент потери пакетов, не отбрасывая datarate до уровней, которые могли быть выше?

EDIT 2: Это произошло со мной, что проблема не может быть точно буфер-переполнения, а не буферная inavailablity. Я использую async WSARecvFrom для получения, который берет буфер, который, как я понимаю, переопределяет буфер OS по умолчанию. Когда датаграмма получена, она подается в буфер, и процедура завершения называется wether, когда буфер заполнен или нет.

В этот момент для обработки входящих данных не существует никакого буфера, пока WSARecvFrom не будет повторно вызван из процедуры завершения.

Вопрос в том, есть ли способ создать какой-то буферный пул, чтобы данные могли буферизироваться при обработке другого буфера?

+0

Вы отправляете пакеты до 127.0.0.1 или на свой внешний IP-адрес? – avakar

+0

@avakar: localhost, aka 127.0.0.1. – 2009-05-20 13:22:27

+0

re your new edit - читать http://tools.ietf.org/html/rfc2309 – Alnitak

ответ

7

В вашем случае вы просто отправляете пакеты слишком быстро, чтобы процесс получения их читал. O/S будет только буферизовать определенное количество принятых пакетов, прежде чем он начнет их отбрасывать.

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

EDIT - по существу, UDP - это «огонь и забыть». В протокол нет механизма обратной связи, например, с TCP. Единственный способ настроить скорость передачи - это дать вам понять, что он не получает весь поток. См. Также RFC 2309.


Re: Пакетные последовательности - повторное упорядочение не происходит из-за физического уровня, как правило, это потому, что сети IP являются «с коммутацией пакетов» в отличие от «с коммутацией каналов».

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

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

+0

Я действительно не понимаю, как это ответ на то, что я спросил? Я написал, что повторный заказ выполняется неявно, и здесь не проблема. Пакетные потери. Вопрос в том, почему они происходят на одной машине, «разговаривающей» с самим собой, и как предотвратить или, по крайней мере, минимизировать ее? – 2009-05-20 13:17:02

+0

это в последнем предложении, но я его развожу ... – Alnitak

+0

Прочтите ответ еще раз, особенно в последнем абзаце. Узким местом является, вероятно, буферизация + низкоуровневая обработка ОС пакетов, которая должна быть в состоянии идти в ногу. –

0

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

Возможно, потому, что протокол позволяет отбрасывать пакеты, когда другие цели - передающие пакеты как можно быстрее - в противном случае не могут быть достигнуты.

Различные результаты могут быть объяснены другими процессами, связанными с трафиком или процессором, на вашем компьютере, вы наблюдали с помощью top (unix) или prcess explorer (nt) во время тестов?

0

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

В случае №1, поскольку вы отправляете на тот же компьютер, сеть даже не задействована, поэтому она должна быть на 100% надежной. Вы не сказали, что у вас две сетевые карты, поэтому я не думаю, что это проблема.

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

В случае № 3 убедитесь, что все ваши сообщения опустились ниже этого предела.

В случае №4, я уверен, что если вы отвечаете максимальному размеру сообщения UDP, тогда вы должны быть в порядке, но там может быть какое-то устаревшее аппаратное или пользовательское устройство с небольшим MTU, которое ваши данные проходят , Если это так, то эти пакеты будут отключены.

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

EDIT: Вы говорите, что ваши пакеты неявно переупорядочены. Я мог бы начать с проверки того, что ваше неявное переупорядочение действительно работает правильно. Это похоже на наиболее вероятный кандидат на вашу проблему.

EDIT # 2: Вы пробовали использовать сетевой монитор. Microsoft (или, по крайней мере, когда-то) использовала бесплатную программу под названием Network Monitor, которая, вероятно, поможет.

2

Если вы используете UDP, единственный способ обнаружить потерю пакетов, насколько мне известно, будет включать некоторую обратную связь.Если вы находитесь в сети с достаточно устойчивой пропускной способностью, вы можете сделать период обучения, в котором вы отправляете пакеты данных, и ждать ответа получателя и рассказать вам, сколько пакетов из полученного пакета (т. Е. Сделать счетчик приемников и после таймаута, ответьте на номер, который он получил). Затем вы просто увеличиваете объем данных за один всплеск, пока не достигнете предела, и немного отбросьте немного, чтобы быть уверенным.

Это позволит избежать ошибок после начального периода оценки, но будет работать только в том случае, если нагрузка на процесс сети/приема не изменяется.

Я уже писал UDP-клиенты на Python и единственный раз, когда я обнаружил значительную потерю пакетов, когда входной буфер в процессе приема был слишком мал. В результате, когда система находилась под большой нагрузкой, вы получили потерю пакетов, потому что буфер молча переполнял.

3

Во избежание проблем с буферами ОС вам необходимо внедрить систему управления скоростью. Он может быть замкнутым (приемник отправляет обратно ACK, а информация о - это буферов) или разомкнутый контур (отправитель замедляется, что означает, что вы должны быть консервативными).

Существуют полустандартные протоколы для UDP для реализации обоих. RBUDP (Reliable Blast UDP) приходит на ум, и есть другие.

+0

+1 для цитирования RBUDP, звучит интересно .... –

+0

После минутного поиска я нашел полезное сравнение [http://www.csm.ornl.gov/~dunigan/netperf/udp/UDP_RBUDP.html ] ... так +1 от меня :-) –

1

Если вы передадите флаг WSA_FLAG_OVERLAPPED на номер WSASocket(), вы можете позвонить по телефону WSARecvFrom() несколько раз, чтобы запросить несколько запросов ввода-вывода. Таким образом, уже есть еще один буфер, доступный для приема следующего пакета, даже до того, как ваша процедура завершения очередности будет выполнять другой запрос ввода-вывода.

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

-1

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

+0

Привет, если вы потеряли доступ к своей учетной записи, вы можете попробовать восстановление учетной записи, или если это не сработает, обратитесь в команду «Переполнение стека». Подробнее см. В [Помощь]. –

Смежные вопросы