2010-06-21 1 views
5

В некоторых случаях я хотел бы явно отказаться от пакетов, ожидающих в сокете, с минимальными накладными расходами. Кажется, нет никакого явного «drop udp buffer» системного вызова, но, может быть, я ошибаюсь?Отказывать входящий пакет UDP без чтения

Следующим лучшим способом может быть, вероятно, recv пакет во временный буфер и просто отказаться от него. Кажется, я не могу получить 0 байт, так как человек говорит о recv: The return value will be 0 when the peer has performed an orderly shutdown. Итак, 1 - это минимум в этом случае.

Есть ли другой способ справиться с этим?

На всякий случай - это не преждевременная оптимизация. Единственное, что делает этот сервер, - это пересылка/отправка пакетов UDP определенным образом - хотя recv с len=1 не убьет меня, я бы скорее просто отбросил всю очередь за один раз с какой-то определенной функцией (надеюсь, задержка).

+0

Какие критерии вы используете, чтобы решить, что отказаться? –

+0

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

ответ

8

Вы можете иметь ядро ​​отменить UDP-пакеты, установив UDP буфер приема в 0.

int UdpBufSize = 0; 
socklen_t optlen = sizeof(UdpBufSize); 
setsockopt(socket, SOL_SOCKET, SO_RCVBUF, &UdpBufSize, optlen); 

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

+1

Это '& UdpBufSize', не так ли? ;) – viraptor

+0

Спасибо за улов! :) – WindsurferOak

+0

Есть ли способ выборочно отбрасывать пакеты из определенного 'sockkaddr' w/o, имеющие' recv' во временный буфер и затем отбрасывая буфер? –

3

Я предпочел бы просто выбросить всю очередь в один идти

Так как это UDP мы говорим здесь: close(udp_server_socket) (розетка)/Bind() еще раз?

Для меня это должно работать.

+0

Это интересное решение ... к сожалению, это не будет работать в привилегированном диапазоне после сброса root (если сокет был связан раньше). Я попробую. – viraptor

+0

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

+0

@viraptor: «это приведет к тому, что ошибки будут возвращены клиенту» - только если клиент работает локально. И клиенты должны игнорировать ошибки от UDP в любом случае (помимо, вероятно, наброса счетчика ошибок), поскольку тип связи в любом случае не является надежным. В противном случае, лично я вижу, что проблема не в том, чтобы просто читать все сообщения: буфер UDP recv по умолчанию достаточно мал, и даже если вы набросаете его на несколько мегабайт, он все еще арахис для современных процессоров. – Dummy00001

1

человек говорит о recv: возвращаемое значение будет равно 0, когда сверстник выполнил упорядоченное завершение работы.

Это не относится к UDP. В UDP нет «соединения» для закрытия. Возвращаемое значение 0 совершенно справедливо, это означает, что датаграмма без получения полезной нагрузки (т. Е. Только заголовки IP и UDP).

Не уверен, что это помогает вашей проблеме или нет. Я действительно не понимаю, куда вы идете с len = 1.

+0

Не совсем верно. Вы можете вызвать соединение через UDP-сокет, из-за чего он будет отклонять пакеты от любого другого хоста: port combo и разрешить доставку сетевых ошибок ICMP в сокет. –

+0

Connect! = Соединение хотя. Нет рукопожатия, без разрыва, без упорядочения пакетов или чего-либо, что большинство людей обычно связывают с соединением. На мой взгляд, соединение является неправильным с UDP и приводит к путанице. – Duck

+0

Я бы не согласился и сказал, что это такая же связь, как и «TCP». Помните, что даже в «TCP» каждый конец поддерживает свое собственное независимое состояние, и если один конец сбой другой, он никогда не узнает об этом, пока не выполнит два посылки и не получит сообщение об ошибке прерывания. Понятие «связь» в моем сознании относится к вопросу о том, говоришь ли ты «много-к-одному» или «один-к-одному» таким образом, который применяется. Конечно, есть аргументы, чтобы увидеть это в любом случае :-) –

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