2016-10-12 1 views
4

J'ai une boucle while(1) qui utilise recvfrom pour obtenir des données qui ont été envoyées à un socket de domaine à partir d'un autre processus (P2). La boucle while doit faire 2 choses, d'abord écouter les données entrantes de P2, et ensuite exécuter une autre fonction checkVoltage().La fonction `recvfrom` peut-elle être utilisée pour vérifier si des données précédentes ont été envoyées à une socket? Ou faut-il écouter activement?

Il court un petit quelque chose comme ceci:

while(true) 
{ 
    listenOnSocket() /*listens for 100 u seconds*/ 
    checkVoltage(); 
} 

Ma question est la suivante: la fonction listenOnSocket() utilise la fonction recvfrom pour vérifier une entrée d'un autre processus. Il passe 100usecs à l'écoute, puis expire et continue à exécuter la fonction checkVoltage(). Donc, il passe 99% du temps dans la fonction listenOnSocket(). Mon problème est que si P2 envoie des informations à la socket pendant la fonction checkVoltage(), il en résultera une erreur, indiquant: sending datagram message: No such file or directory.

Existe-t-il un moyen de faire vérifier par cette boucle si des données ont déjà été envoyées au socket? De cette façon, si P2 envoie des données pendant la fonction checkVoltage(), cela n'entraînera pas d'erreur.

Merci.

EDIT:

Ainsi, la fonction crée listenOnSocket() une prise avec le nom FireControl quand je lance P1 (le programme qui reçoit des données de P2) le fichier FireControl disparaît pour une fraction de seconde puis réapparaît. Si P2 envoie des données à P1 pendant cette courte période, il en résulte l'erreur mentionnée en haut.

Donc je suppose que cela signifie que je devrais séparer la création de la socket de la fonction recvfrom, parce que la courte période où la nouvelle socket est créée n'existe pas - si cela a du sens.

Je suis un dope, j'aurais dû les séparer en premier lieu!

EDIT2: Voici listenOnSocket():

command listenOnSocket(int timeout, float utimeout) /*Returns null payload when no input is detected*/ 
{ 
    command payload; 
    int sock; 
    socklen_t* length; 
    struct sockaddr_un name; 
    char buf[1024]; 

    struct timeval tv; 
    tv.tv_sec = timeout; 
    tv.tv_usec = utimeout; 

    /* Create socket from which to read. */ 
    sock = socket(AF_UNIX, SOCK_DGRAM, 0); 
    if (sock < 0) 
    { 
     perror("opening datagram socket"); 
     payload = nullPayload; 
    } 

    /* Create name. */ 
    name.sun_family = AF_UNIX; 
    strcpy(name.sun_path, NAME); 

    unlink(name.sun_path); 

    /* Bind the UNIX domain address to the created socket */ 
    if (bind(sock, (struct sockaddr *) &name, sizeof(struct sockaddr_un))) 
    { 
     perror("binding name to datagram socket\n"); 
     payload = nullPayload; 
    } 

    /*Socket has been created at NAME*/ 
    if (timeout != 0 || utimeout != 0) 
    { 
     setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(struct timeval)); 
    } 
    else 
    { 
     tv.tv_sec = 0; 
     tv.tv_usec = 0; 
     setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(struct timeval)); 
    } 
    /* Read from the socket */ 
    if (recvfrom(sock, &payload, sizeof(command), 0, (struct sockaddr *)&name, &length) < 0) /*Less than zero results from a timeout*/ 
    { 
     payload = nullPayload; 
    } 

    unlink(NAME); 
    return payload; 
} 

et la boucle est ici qu'il appelle:

while (1) 
    { 
     buffer = getADCValue(); 

     checkVoltage(); 

     temp = listenOnSocket(0, 100); /*Look for a new command*/ 
     doStuffWithTempIfItHasChanged(); 
     } 
    } 
+0

"envoyé à un socket de domaine" -> étant donné le tag, ai-je raison de supposer que vous voulez dire socket de domaine UNIX? – zneak

+0

Etes-vous sûr que votre socket fonctionne?AFAIK, vous ne devriez pas avoir besoin d'être coincé dans 'recvfrom' pour un appel' send'/'sendto' de P2 pour terminer avec succès, les messages devraient être mis en file d'attente à condition que le socket existe. – zneak

+0

@zneak oui, ceci est un socket de domaine unix (fonctionnant sur Raspbian). Les sockets fonctionnent vraiment, dans une autre section du code, j'exécute 'listenOnSocket' sans timeout, et le programme se trouve sur la fonction' recvfrom' pendant qu'il attend l'entrée. –

Répondre

1

Une fois que vous avez lié la prise, les datagrammes s'accumule dans un tampon et peut être lu plus tard en utilisant recvfrom. Cela dit, si la mémoire tampon déborde, les messages peuvent être rejetés.

2

Je suppose que cela signifie que je dois séparer la création de la prise de la fonction recvfrom, car la courte période où le nouveau socket est créé, il n'existe pas

C'est exact. Si vous ouvrez et fermez le socket à chaque fois dans votre socket listenOnSocket(), (a) vous perdrez tous les datagrammes qui ont été mis en file d'attente que vous n'avez pas lus, et (b) envoie alors que le socket est fermé échouera ... bien sûr. Rien pour eux à envoyer.