Как отбросить входящие пакеты в необработанном сокете?

StackOverflow https://stackoverflow.com/questions/209305

Вопрос

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

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

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

Это было полезно?

Решение

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

Другие советы

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

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

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

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

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

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

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

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top