Comment vider la mémoire Tampon d'Entrée de l'UDP Socket en C?
Comment vider la mémoire Tampon d'Entrée (si une telle chose existe) d'une Socket UDP en C ?
Je suis en train de travailler sur un Linux embarqué environnement et l'utilisation de C pour créer des applications natives. Il y a plusieurs de ces machines sur le même réseau, et lorsqu'un événement se produit sur l'un d'eux (appelons cela le dénonciateur), dénonciateur doit envoyer un message réseau à l'adresse de diffusion réseau, de sorte que toutes les machines sur le réseau (y compris la dénonciation) sait à propos de l'événement et exécute certaines actions en fonction de cela. Je suis en utilisant le socket UDP par le chemin...
Voici le pseudo-code:
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;
}
}
}
La façon dont je attendent et souhaitent de travail de ce code est:
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
La façon dont il fonctionne réellement est:
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: Les paquets/messages/Diffusions UDP envoyés à un déjà lié socket, whoose parent fil est de dormir à la livraison-moment; sont en quelque sorte mis en file d'attente/tampon et livré au cours de la prochaine "recvfrom' appel sur le dit support.
Je veux ces diffusions UDP être ignoré alors que je pensais de vider le tampon de réception (évidemment pas celui que je suis en donnant comme paramètre à la recvfrom méthode), s'il existe, avant d'appeler recvfrom. Comment puis-je le faire? ou quel chemin dois-je suivre?
Vous devez vous connecter pour publier un commentaire.
Veuillez noter que la notion de "rinçage" ne s'applique qu'à la sortie. Un flush vide la mémoire tampon, et assure que tout a été envoyé à sa destination. Concernant un tampon d'entrée, les données sont déjà à sa destination. Tampons d'entrée peut être lu ou effacée, mais pas "vidé".
Si vous voulez juste vous assurer que vous avez tout lu dans la mémoire tampon d'entrée, ce que vous cherchez est un non-bloquant opération de lecture. Si vous l'essayez, et il n'y a pas d'entrée, il doit retourner une erreur.
select
(linux.die.net/man/2/select) est disponible? Si vous le faites, vous pouvez utiliserselect
pour déterminer si une entrée est disponible et n'appelez votre blocage de la fonction de lecture lorsque vous en avez besoin. Si vous avez une telle fonction disponible, je recommande l'utilisation deselect
et de non-blocage I/O (blocage de lecture fonctions sont parfois mises en œuvre à l'interne comme àselect
+ non-blocage de lire de toute façon). Ce serait vous donner plus de flexibilité et de contrôle plutôt que de bloquer les I/O.recvfrom
vous au lieu d'appeler une fonction qui permettrait de récupérer des données à partir de l'I/O loop (les garder sur une file d'attente interne, par exemple).Un socket a un seul tampon de réception à l'intérieur de la pile TCP/IP. Il s'agit essentiellement d'une FIFO de la datagrammes reçus. TCP et UDP poignée de que la file d'attente différemment si. Lorsque vous appelez
recv(2)
sur un socket UDP vous dequeue un seul datagramme à partir de la mémoire tampon. TCP organise les datagrammes dans un flux d'octets en fonction de la séquence de nombres. En cas de recevoir les dépassements de tampon dans le datagramme est abandonné par la pile. TCP tente de le renvoyer dans ce cas. UDP n'est pas. Il n'y a pas explicite "flush" pour le du tampon de réception, puis d'autres la lecture de la prise ou de fermeture.Edit:
Vous avez inhérents à la condition de course dans votre application et il semble que vous essayez de le résoudre avec un mauvais outil (pile TCP/IP). Ce je pense que que vous devriez faire est de définir un état de propreté de la machine pour l'application. Gérer les événements qui font sens à l'état actuel, ignorer les événements qui ne le sont pas.
Une autre chose à regarder est l'utilisation de la multidiffusion au lieu de diffusion. C'est un peu plus compliqué mais vous aurez plus de contrôle sur les "abonnements" par entrer/sortir de groupes de multidiffusion.