Как отбросить входящие пакеты в сырой сокет? - PullRequest
3 голосов
/ 16 октября 2008

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

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

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

Ответы [ 7 ]

5 голосов
/ 21 октября 2008

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

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

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

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

2 голосов
/ 23 октября 2008

Я бы порекомендовал вообще не спать. Используется вызов 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.

1 голос
/ 21 октября 2008

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

1 голос
/ 16 октября 2008

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

0 голосов
/ 18 августа 2010

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

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

0 голосов
/ 21 октября 2008

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

for(n=0;n<=MAX_BUFFER_SIZE;n++)
{
recv_buffer[n] = 0;
}
0 голосов
/ 17 октября 2008

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

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

...