Как промыть входной буфер UDP-сокета в C?



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



Я работаю над встроенной средой Linux и использую C для создания собственного приложения. Существует несколько таких встроенных машин в одной и той же сети, и когда на одной из них происходит событие (назовем его информатором), информатор должен отправить сетевое сообщение на сетевой широковещательный адрес, чтобы все машины в сети (включая информатора) знали об этом событии. событие и выполняет некоторые действия в соответствии с ним. Кстати, я использую 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. Как я могу это сделать? или по какому пути мне идти?

731   2  

2 ответов:

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

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

Сокет имеет один буфер приема внутри стека TCP / IP. Это, по сути, ФИФО полученных датаграмм. TCP и UDP обрабатывают эту очередь по-разному. Когда вы вызываете recv(2) на сокете UDP, выизвлекаете единственную дейтаграмму из этого буфера. TCP упорядочивает дейтаграммы в поток байтов в соответствии с порядковыми номерами. Когда буфер приема переполняется, дейтаграмма отбрасывается стеком. TCP пытается повторно отправить в этом случае. UDP этого не делает. явная функция "flush" для буфера приема, кроме чтения сокета или его закрытия.

Правка:

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

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

Comments

    Ничего не найдено.