#c #boost #cross-platform #udp
#c #повышение #кроссплатформенный #udp
Вопрос:
Я разрабатываю кроссплатформенный инструмент, который захватывает несколько потоков udp с различной скоростью передачи данных. boost::asio используется для создания сети. Есть ли какой-либо способ обнаружить ситуацию, когда буфер udp был заполнен и могла произойти потеря данных в сокете? Единственный способ, который я вижу сейчас, — это чтение /proc/%pid% / net / udp, но это не применимо для Windows, как вы знаете :). Также я хотел бы использовать для этого функции boost, если это возможно.
Комментарии:
1. Это не принесло бы вам многого. Ваш локальный буфер является лишь одним из многих мест, где эти UDP-пакеты могли быть сброшены по маршруту.
2. Спасибо, я знаю, что такое udp. Но потоки огромны (десятки / сотни Мбит / с), и обработка сложна. Поэтому было бы неплохо обнаружить ситуацию, когда ресурсов недостаточно для обработки такого объема данных.
Ответ №1:
Если вам нужна эта возможность, вы должны закодировать ее в протокол, который вы используете. UDP не способен сделать это сам. Например, вы могли бы поместить порядковый номер в каждую дейтаграмму. Отсутствующие дейтаграммы будут соответствовать отсутствующим порядковым номерам.
Комментарии:
1. О, было бы неплохо использовать это решение, но я не могу вносить изменения в протокол.
2. Проверка, чтобы увидеть, предоставляет ли протокол какой-либо другой способ. Трудно представить, как протокол был бы полезен, если бы он не предоставлял способа оценить, удалялись ли данные.
Ответ №2:
Я только что столкнулся с той же проблемой (хотя для меня специфичен для Linux), и, несмотря на то, что вопрос старый, я мог бы также документировать свои выводы для других.
Насколько я знаю, для этого нет переносимого способа, и Boost напрямую ничего не поддерживает.
Тем не менее, есть несколько способов сделать это в зависимости от платформы. В Linux это можно сделать, установив параметр сокета SO_RXQ_OVFL, а затем получая ответы с помощью recvmsg(). Хотя это плохо документировано, но вам может помочьhttp://lists.openwall.net/netdev/2009/10/09/75.
Один из способов избежать этого в первую очередь — увеличить буферы приема (я предполагаю, что вы уже исследовали это, но включили его для полноты). Параметры SO_RCVBUF кажутся довольно хорошо поддерживаемыми кроссплатформенными. http://pubs.opengroup.org/onlinepubs/7908799/xns/setsockopt.html http://msdn.microsoft.com/en-us/library/windows/hardware/ff570832 (v = против 85).aspx OS: es устанавливает для этого верхний предел, который администратору, возможно, придется увеличить. В Linux, т.е. его можно увеличить с помощью /proc/sys/net /core/rmem_max.
Наконец, одним из способов для вашего приложения оценить его «нагрузку», которая при больших входных буферах может служить для раннего обнаружения перегрузки, может заключаться в том, чтобы ввести временную метку до и после асинхронных операций. В псевдокоде (не с поддержкой boost::async-adapted):
work_time = 0
idle_time = 0
b = clock.now()
while running:
a = clock.now()
work_time = a-b
data = wait_for_input()
b = clock.now()
idle_time = b-a
process(data)
Затем примерно каждую секунду вы можете проверять и сбрасывать work_time / (work_time idle_time)
. Если оно приближается к 1, вы знаете, что приближаетесь к проблеме, и можете отправить предупреждение или предпринять другие действия.
Комментарии:
1. Спасибо за упоминание SO_RXQ_OVFL. Просто чтобы добавить, здесь есть полезный пример его использования: github.com/linux-can/can-utils/blob/master/candump.c