Как очистить входной буфер сокета UDP в C?

Как очистить входной буфер (если такая вещь вообще существует) UDP Socket в 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, отправленные в уже привязанный сокет, whoose parent thread – спящий момент доставки; как-то поставлены в очередь / буферизированы и доставлены при следующем вызове «recvfrom» на указанном сокете.

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

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

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

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

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

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

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