Максимальный размер очереди icmp пакетов linux

Есть приложение для пинга через icmp echo. При этом recvfrom делаю только тогда, когда отправил какой-то запрос, при этом за время, когда из сокета ничего не получаю могут копиться пакеты. Какой максимальный размер очереди icmp пакетов в Linux? Код асинхронный, выполняется в одном потоке и зависать на разборе очереди на долго не хотелось бы.


Ответы (2 шт):

Автор решения: Fat-Zer

Максимальный размер буфера конкретного сокета можно задать/узнать с помощью setsockopt()/getsockopt(), а конкретно с помощью опции SO_RCVBUF:

int buf_sz;
socklen_t opt_sz = sizeof(int);
int rc = getsockopt(sock, SOL_SOCKET, SO_RCVBUF, &buf_sz, &opt_sz);
assert(rc==0 && opt_sz == sizeof(int));

Значение по умолчанию для этого параметра устанавливается через /proc/sys/net/core/rmem_default, а максимальное возможное значение — через /proc/sys/net/core/rmem_max.

Процесс с правами root'а (точнее с мандатом CAP_NET_ADMIN) может запросить и больший размер буфера с помощью SO_RCVBUFFORCE.

Аналогичные опции для буфера отправки называется SO_SNDBUF/SO_SNDBUFFORCE.


При этом recvfrom делаю только тогда, когда отправил какой-то запрос, при этом за время, когда из сокета ничего не получаю могут копиться пакеты.

Если привилегии не сброшены, то правильным решением тут ИМХО было бы закрывать сокет, когда он не используется и открывать заново. Или же вообще вынести эту функциональность в отдельный хелпер. Если дело именно в ping'е, то я бы просто использовал бы системную утилиту.

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

int sz = 0; //< скорей всего реальный размер на linux будет 256
setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &sz, sizeof(int));
// TODO: проверить, что 0 здесь — корректное значение

А перед тем как снова начать читать увеличивал бы обратно чистил бы его (последнее в принципе не обязательно):

setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &buf_sz, sizeof(int));
while (recv(sock, 0, 0, MSG_DONTWAIT) !=-1 ) {}
if (errno != EAGAIN) {
  perror("socket error"); 
  exit(EXIT_FAILURE); 
} else {
  errno = 0;
}
→ Ссылка
Автор решения: Sergey

В своё время мой младшенький писал курсовой на эту тему :-) У него была локалка типа 192.168.0.*/24 которую надо было просканировать как можно быстрее.

Он просто создавал 254 нити (2 - это резервные адреса) и в каждой нитке делал отдельный пинг. Благодаря этому не возникало никаких проблем и работало всё исключительно быстро.

→ Ссылка