Как очистить входной буфер UDP-сокета в C? - PullRequest
2 голосов
/ 20 февраля 2010

Как очистить входной буфер (если такая вообще существует) UDP-сокета в C?

Я работаю над встроенной средой Linux и использую C для создания собственного приложения.В одной сети есть несколько таких встроенных машин, и когда на одной из них происходит событие (назовем его WHISTLE-BLOWER), WHISTLE-BLOWER должен отправить сетевое сообщение на сетевой широковещательный адрес, чтобы все машины были включены.сеть (включая WHISTLE-BLOWER) знает о событии и выполняет некоторые действия в соответствии с ним. Кстати, я использую сокет UDP ...

Вот псевдокод для него:

main
{
    startNetworkListenerThread( networkListenerFunction );

    while( not received any SIGTERM or such )
    {
        localEventInfo = checkIfTheLocalEventOccured();
        broadcastOnNetwork( localEventInfo );
    }
}

networkListenerFunction
{
    bindSocket;

    while( not SIGTERM )
    {
// THIS IS WHERE I WANT TO FLUSH THE RECV BUFFER...
        recv_data = recvfrom( socket );
        if( validate recv data )
        {
            startExecuteLocalAction;
            sleep( 5 );
            stopExecuteLocalAction;
        }
    }
}

То, как я ожидаю и хочу для работы этот код:

1. LOCAL_EVENT occured
2. Broadcasted LOCAL_EVENT_INFO on network
3. All machines received EVENT_INFO, including the original broadcaster
4. All machines started executing the local action, including the original broadcaster
5. All machines' network listener(thread)s are sleeping
6. Another LOCAL_EVENT2 occured
7. Since all machines' listener are sleeping, LOCAL_EVENT2 is ignored
8. All machines' network listener(thread)s are now active again
9. GO BACK TO 1 / RESTART CYCLE
RESULT = TOTAL 2 EVENTS, 1 IGNORED

На самом деле он работает так:

1. LOCAL_EVENT occured
2. Broadcasted LOCAL_EVENT_INFO on network
3. All machines received EVENT_INFO, including the original broadcaster
4. All machines started executing the local action, including the original broadcaster
5. All machines' network listener(thread)s are sleeping
6. Another LOCAL_EVENT2 occured
7. Eventhough all machines' listener are sleeping; LOCAL_EVENT2 is queued  SOMEHOW
8. All machines' network listener(thread)s are now active again
9. All machines received EVENT_INFO2 and executed local actions again, slept and reactivated
10. GO BACK TO 1 / RESTART CYCLE
RESULT = TOTAL 2 EVENTS, 0 IGNORED

tl, dr: Пакеты / сообщения / UDP-рассылки, отправленные науже привязанный сокет, родительский поток которого спит в момент доставки;каким-то образом ставятся в очередь / буферизуются и доставляются при следующем вызове recvfrom на указанном сокете.

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

Ответы [ 2 ]

3 голосов
/ 20 февраля 2010

Обратите внимание, что понятие «промывка» относится только к выходу.Сброс очищает буфер и гарантирует, что все в нем было отправлено к месту назначения.Что касается входного буфера, данные уже находятся в месте назначения.Входные буферы могут считываться или очищаться, но не «сбрасываться».

Если вы просто хотите убедиться, что вы прочитали все во входном буфере, вы ищете неблокирующую операцию чтения,Если вы попробуете это сделать, и нет ввода, он должен вернуть ошибку.

1 голос
/ 20 февраля 2010

Сокет имеет один буфер приема внутри стека TCP / IP.По сути, это FIFO полученных дейтаграмм.TCP и UDP по-разному обрабатывают эту очередь.Когда вы вызываете recv(2) на сокете UDP, вы удаляете единственную дейтаграмму из этого буфера.TCP организует дейтаграммы в поток байтов в соответствии с порядковыми номерами.При переполнении приемного буфера дейтаграмма сбрасывается в стек.TCP пытается переслать в этом случае.UDP не делает.Не существует явной функции «сброса» для буфера приема, кроме чтения сокета или его закрытия.

Редактировать:

В вашем приложении есть состояние гонки, и похоже, что вы пытаетесьчтобы решить это с неправильным инструментом (стек TCP / IP). Я думаю, , что вам следует сделать, - определить чистый конечный автомат для приложения.Обрабатывайте события, которые имеют смысл в текущем состоянии, игнорируйте события, которые этого не делают.

Еще одна вещь, на которую стоит обратить внимание, это использование многоадресной рассылки вместо широковещательной.Это немного сложнее, но вы сможете лучше контролировать «подписки», присоединяясь к групповым группам или покидая их.

...