8
votes

lire () ne bloque pas dans la programmation de la prise

J'ai un serveur qui envoie des données à un client toutes les 5 secondes. Je souhaite que le client bloque sur lire () jusqu'à ce que le serveur envoie des données, puis imprimez-la. Je sais que lire () bloque par défaut. Mon problème est que mon client ne bloque pas de lecture (). C'est très étrange et cela ne semble pas être un problème normal.

mon code imprime "rien de rentré" dans une boucle infinie. Je suis sur une machine Linux, programmation en c. Mon extrait de code est ci-dessous. S'il vous plaît des conseils. P>

while(1)
{
    n = read(sockfd, recvline, MAXLINE);
    if ( n > 0) 
    {
        recvline[n] = 0;    
        if (fputs(recvline, stdout) == EOF)
            printf("fputs error");
    }
    else if(n == 0)
        printf("Nothing came back");
    else if (n < 0)
        printf("read error");
}
return; 


5 commentaires

Avez-vous vérifié que la connexion est ouverte (i.e sockfd est valide)?


Une valeur de retour de 0 à partir de lecture () signifie que l'autre extrémité (le serveur) a fermé la prise.


@Ed Heal: Oui, c'est valide. J'ai un chèque pour ça.


@Greg: Eh bien, la chose est que le serveur envoie des données toutes les 5 secondes. Sauf si le client attend que le serveur envoie, il obtiendra 0 à chaque fois.


Non ce ne sera pas. Zéro signifie que la paite a fermé la connexion. Cela ne signifie jamais qu'il n'y avait pas de données. En mode blocage, lire () bloquera; En mode non bloquant s'il n'y a pas de données, il retournera -1 avec errno défini sur Eagain ou EwouldBlock en fonction de votre plate-forme.


3 Réponses :


11
votes

Il peut y avoir plusieurs causes et plusieurs exceptions sont possibles à différents endroits:

  1. Vérifiez la prise de contrôle où vous créez: p>

    n = read(sockfd, recvline, MAXLINE);
    if(n < 0){  
        perror("Read Error:");
    }  
    
  2. vous et activez également le mode de blocage explicitement avant d'l'utiliser: p>

     struct timeval t;    
     t.tv_sec = 0;
     tv_usec = 0;
     setsockopt(
          sockfd,     // Socket descriptor
          SOL_SOCKET, // To manipulate options at the sockets API level
          SO_RCVTIMEO,// Specify the receiving or sending timeouts 
          const void *(&t), // option values
          sizeof(t) 
      );   
    
  3. Vérifiez l'appel de la fonction de lecture (raison du bogue) p>

    sockfd=socket(AF_INET,SOCK_STREAM,0);  
    if (sockfd==-1) {
        perror("Create socket");
    }
    
  4. aussi Vérifiez le code du serveur strong>!: p>

    1. Que votre serveur envoie une charte (s) blanche (non imprimable, null, entrée). Et vous n'êtes pas au courant de cela. Bug vous code serveur aussi. p> li>

    2. ou votre serveur terminé avant que votre client puisse lire forte>. p> li> ol> blockQuote> li>

    3. une chose plus intéressante forte>, essayez de comprendre: p>

      Lorsque vous appelez n écriture () code> au serveur, il n'est pas nécessaire, il devrait y avoir n lire () code> appel de l'autre côté. P> blockQuote> li> ol> p>


5 commentaires

Merci pour la réponse élaborée, homme. Je vais essayer de corriger le serveur de bugs et voir si elle envoie des trucs bizarres.


Le mode blocage est la valeur par défaut: vous n'avez pas à la définir explicitement. Le code dans (2) que les appels SetSockopt () avec des arguments de & 0 et Tailleof (SOCKFD) est un non-sens complet et ne compilera pas. Downvote.


@EJP: Je sais que le mode par défaut bloque. Je voulais juste dire comment définir explicitement le mode blocage (ou réinitialiser le mode blocage). Pour la compilation Erreur: j'ai corrigé l'option Code de SetSock () et ma demande de votre demande: VEUILLEZ VÉRIFIER ET SI SI SI NON TOUT NON VEUT VEUILLEZ RECTIFIER afin que l'on puisse obtenir de l'aide correcte..Merci EJP!


@Grijeshchauhanhan merci beaucoup d'avoir aidé!


Assurez-vous également que votre tampon de réception et sa taille est "initialisée" correctement. E.g Dans ce cas RECVLINE et MAXLINE



1
votes

Quelle est la valeur de maxline?

Si la valeur est 0, il retournera également 0. Sinon, comme l'a mentionné Grijesh Chauhan, réglez-le explicitement à bloquer. P>

ou, vous pouvez également envisager d'utiliser RECV () lorsque le blocage et le non-blocage peuvent être spécifiés. Il a l'option, msg_waittall, où il bloquera jusqu'à ce que tous les octets arrivés. P>

n = recv(sockfd, recvline, MAXLINE, MSG_WAITALL);


0 commentaires

3
votes

Qu'est-ce que Greg Hewgill a déjà écrit en tant que commentaire: un EOF (c'est-à-dire un arrêt explicite d'écriture, que ce soit via fermer () ou via arrêt () ) sera communiqué au côté de la réception en ayant recv () retour 0. Donc, si vous obtenez 0, vous savez qu'il n'y aura pas de données et vous pouvez mettre fin à la boucle de lecture.

Si vous aviez activé sans blocage et qu'il n'y a pas de données, vous obtiendrez -1 et errno sera défini sur eagain ou ewouldblock .


1 commentaires

Je ne pense pas que ce soit le problème. Le serveur est dans une boucle infinie, il conserve l'envoi de données au client toutes les 5 secondes. Le serveur, ByDesign, n'est pas censé disparaître du tout.