UDP-пакеты Winsock отбрасываются? - PullRequest
10 голосов
/ 02 октября 2009

У нас есть система связи клиент / сервер по настройке UDP в Windows. Проблема, с которой мы сталкиваемся, заключается в том, что при увеличении пропускной способности пакеты отбрасываются. Мы подозреваем, что это связано с приемным буфером UDP, который постоянно опрашивается, вызывая блокировку буфера и отбрасывание любых входящих пакетов. Возможно ли, что чтение этого буфера приведет к удалению входящих пакетов? Если так, какие варианты исправить это? Система написана на C. Пожалуйста, дайте мне знать, если это слишком расплывчато, и я могу попытаться предоставить больше информации. Спасибо!

Ответы [ 6 ]

12 голосов
/ 02 октября 2009

Размер буфера сокета по умолчанию в сокетах Windows составляет 8 КБ или 8192 байта. Используйте функцию setsockopt Windows, чтобы увеличить размер буфера (см. Параметр SO_RCVBUF).

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

Обычно для такой ситуации требуется два потока.

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

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

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

5 голосов
/ 02 октября 2009

Да, стеку разрешено отбрасывать пакеты & mdash; тихо, даже & mdash; когда его буферы переполняются. Это является частью природы UDP, одной из составляющих надежности, которую вы теряете при переключении с TCP. Вы можете заново изобрести TCP & mdash; плохо & mdash; добавив логику повторных попыток, пакеты ACK и т. д., или вы можете переключиться на что-то промежуточное, например SCTP .

Есть способы увеличить размер буфера стека, но это в значительной степени упускает из виду. Если вы не читаете достаточно быстро, чтобы сохранить доступное пространство буфера, увеличение буферов только отодвинет время, которое уходит на то, чтобы освободить пространство буфера. Правильным решением является создание больших буферов в вашем собственном коде и перемещение данных из буферов стека в буфер вашей программы КАК МОЖНО СКОРЕЕ, где он может ожидать обработки в течение сколь угодно долгого времени.

3 голосов
/ 02 октября 2009

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

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

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

4-й шаг: проверьте сетевое оборудование, коммутаторы и т. Д., Чтобы получить подробную информацию об их статистике трафика, переполнении буфера и т. Д. - если это необходимо, найдите более быстрые коммутаторы или, возможно, отключите неисправный

... просто к вашему сведению, я постоянно использую многоадресный UDP-трафик на нашем бэкэнде на avg. ~ 30 Мбит / с с пиковыми значениями 70 Мбит / с, и моя скорость выпадения равна нулю

3 голосов
/ 02 октября 2009

Возможно ли, что чтение этого буфера приведет к удалению входящих пакетов?

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

Если это так, какие варианты исправить это?

Один из вариантов - изменить сетевой протокол: использовать TCP или реализовать некоторое подтверждение + «управление потоком» с использованием UDP.

В противном случае вам нужно понять, почему вы не читаете достаточно быстро / часто.

Если ЦП загружен на 100%, вам нужно выполнять меньше работы с пакетом или получать более быстрый ЦП (или использовать многопоточность и большее количество ЦП, если вы этого еще не сделали).

Если процессор не на 100%, то, возможно, происходит следующее:

  • Вы читаете пакет
  • Вы выполняете некоторую работу, которая занимает x мсек реального времени, часть из которых затрачивается на другие операции ввода-вывода (поэтому процессор не занят, но не используется для чтения другого пакета)
  • В течение этих x msec приходит поток пакетов, а некоторые отбрасываются

Лекарством от этого может быть изменение резьбы.

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

Другая возможность состоит в том, чтобы увидеть, есть ли (O / S-специфичная) опция конфигурации для увеличения количества принятых пакетов UDP, которые сетевой стек готов буферизировать, пока вы не попытаетесь их прочитать.

0 голосов
/ 02 октября 2009

Пакеты могут быть потеряны из-за увеличения несвязанного сетевого трафика в любом месте маршрута или полных буферов приема. Чтобы смягчить это, вы можете увеличить размер буфера приема в Winsock.

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

0 голосов
/ 02 октября 2009

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

Я предполагаю, что вы используете select () для опроса сокета? Насколько я знаю, не может вызвать падение.

...