Как отбросить входящие пакеты в необработанном сокете?
-
03-07-2019 - |
Вопрос
Я пишу приложение 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.Протокол между потоком ввода-вывода и уровнем приложения может варьироваться от простой асинхронной очереди до более сложной тематической фильтрации, списков приоритетов и поддержки пулов потоков для параллельного декодирования входящих данных.