2008-10-16 7 views
3

Я пишу приложение C/C++ под Linux, которое считывает данные из сырого сокета (для ICMP-пакетов). Вопрос: есть ли способ отбросить все данные, которые все еще поставлены в очередь на сокет?Как удалить входящие пакеты в raw-сокете?

Проблема в том, что после сна какое-то время есть данные, стоящие в очереди на сокет, который мне неинтересен; поэтому было бы лучше всего сказать сокету «забыть все данные, которые вы забуферили прямо сейчас», так что, если я перейду в цикл select()/recvfrom(), я получаю только данные, полученные недавно.

Есть ли лучший способ, чем первый цикл опроса()/recvfrom()? Может быть, какой-то сокет API? Портативный, даже? :-)

ответ

1

Разве вы не можете просто сделать recvfrom() во временный буфер и сбросить буфер?

+0

Да, вот что я в итоге сделал ...Вместо вызова sleep() я использую select() с таймаутом, и если вызов select() указывает на входящие данные, данные принимаются с recvfrom() и игнорируются, и создается новый select(), пока сон не будет время вышло. – oliver 2008-10-22 10:14:39

1

Единственный способ, которым я знаю, как это сделать надежно, - закрыть розетку.

+0

Вполне возможно, лучшее решение в этом случае - это просто, по крайней мере. – MarkR 2009-03-22 19:23:11

0

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

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

0

Можете ли вы сделать что-то подобное прямо перед сном?

for(n=0;n<=MAX_BUFFER_SIZE;n++) 
{ 
recv_buffer[n] = 0; 
} 
5

Во время простоя, можно отключить сокет, установив Размер буфера приема к нулю:

int optval = 0; /* May need to be 1 on some platforms */ 

setsockopt(sockDesc, SOL_SOCKET, SO_RCVBUF, (char *)(&optval), sizeof(optval)); 

Повторное включение путем установки «optval» до большего буфера (например, 4096).

+0

Действительно ли это работает? Если это так, это звучит неплохо. – MarkR 2009-03-22 19:22:40

2

Я бы рекомендовал не спать вообще. Запрашивается с помощью вызова select для обработки данных сразу же после его поступления.

while (1) 
{ 

    FD_ZERO (&sockets); 
    FD_SET (raw_socket, &sockets); 

    timeout.tv_sec = 1; 
    timeout.tv_usec = 0; 

    if (select (raw_socket + 1, &sockets, NULL, NULL, &timeout)) 
    { 
    if (FD_ISSET (raw_socket, &sockets)) 
    { 
     // handle the packet 
    } 
    } 
    else 
    { 
    /* Select Timed Out */ 
    fprintf(stderr, "Timed out"); 
    } 
} 

Кроме того, при создании сырого сокета вы можете указать, что вас интересуют только пакеты icmp.

0

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

Это архитектура за TIBCO Rendezvous, используемая во многих рыночных данных реального времени и корпоративных системах обмена сообщениями. Предостережение в том, что вы обычно хотите ограничить размер очереди, чтобы приложение не получало от менеджера OOM. Протокол между потоком ввода-вывода и уровнем приложения может варьироваться от простой асинхронной очереди до более сложной фильтрации объектов, списков приоритетов и поддержки пулов потоков для параллельного декодирования входящих данных.

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

  • Нет связанных вопросов^_^