Maison  >  Questions et réponses  >  le corps du texte

linux - Erreur de programme client-serveur Le programme a reçu le signal SIGPIPE, tuyau cassé.

Entrez d'abord le code :

//server
void newConnection(int sockfd,const InetAddress &addr)
{
    ::write(sockfd, "how are you?\n", 13); //简单地回复一句话
}

int main()
{
    EventLoop loop;
    InetAddress listenAddr(12345);
    Acceptor acceptor(&loop, listenAddr);
    acceptor.setConnectionCallback(newConnection);    //listenfd可读(新连接)调用回调
    acceptor.listen();    //Accept::listen调用listenfd的listen
    
    //while(true)循环,Acceptor构造时讲listenfd放进loop的epoll结构中,
    //本循环检测到listenfd可读(新连接)之后调用accept得到connfd,然后调用上面set的回调函数
    loop.loop();
}


//client
int main(int argc, char **argv)
{
    struct sockaddr_in addr;
    bzero(&addr, sizeof addr);
    addr.sin_family = AF_INET;
    addr.sin_port = htons(12345);
    inet_pton(AF_INET, argv[1], &addr.sin_addr);

    int sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    
    connect(sockfd, (struct sockaddr *)&addr, sizeof(addr)); //连接server
    char buf[256] = {'rrreee'};
    read(sockfd, buf, sizeof(buf)); //接受msg
    printf("Received: %s\n", buf);

    close(sockfd);

    return 0;
}

Le déroulement complet du programme est à peu près le suivant :
Après le démarrage du serveur, l'accepteur est dans l'état d'écoute, puis le client demande une connexion. Si la connexion réussit, le serveur appelle le rappel newConnection pour envoyer "comment allez-vous". " au client, et celui-ci l'imprime après l'avoir accepté.

Voici la situation d'erreur :
En utilisant le débogage gdb, j'ai constaté qu'à chaque fois ::write(sockfd, "how are you?n", 13);就会接收到SIGPIPE le programme meurt.

J'ai vérifié Le programme a reçu le signal SIGPIPE, tuyau cassé.La raison serait l'écriture sur un sockfd invalide (non connecté ou déconnecté). Mais lorsque mon programme exécute l'écriture de la fonction de rappel, la connexion ne se ferme pas. (Pour le débogage, j'ai également commenté la fermeture qui apparaît dans tous les codes)

De plus, lors du débogage de gdb pour écrire, j'ai également utilisé ll /proc/pid/fd pour vérifier le descripteur d'occupation actuel du système, et connfd existe toujours.

Donc je ne comprends pas du tout pourquoi il y a SIGPIPE, merci de me donner quelques conseils !

仅有的幸福仅有的幸福2713 Il y a quelques jours722

répondre à tous(1)je répondrai

  • 我想大声告诉你

    我想大声告诉你2017-05-16 13:20:39

    Résolu, la raison est que le troisième paramètre de ::accept est mal transmis

    Dans mon code, le wrapper d'acceptation est le suivant :

    Accept(int listenfd, struct sockaddr *addr)
    {
        socklen_t len = sizeof(*addr);
        int connfd = ::accept(listenfd, addr, &len);
        //...
    }

    Le code d'appel est

    struct sockaddr_in addr;
    //...
    int connfd = Accept(listenfd, &addr);

    L'erreur devrait être que le troisième paramètre de ::accpet doit recevoir la taille du sockaddr_in d'origine au lieu de la taille du sockaddr converti. Modifié comme suit :

    Accept(int listenfd, struct sockaddr_in *addr)
    {
        socklen_t len = sizeof(*addr);
        int connfd = ::accept(listenfd, (struct sockadr*)addr, &len);
        //...
    }

    Publier unman 2 accept :

    L'argument addrlen est un argument valeur-résultat : l'appelant doit l'initialiser pour contenir la taille (en octets) de la structure pointée par addr ; au retour, il contiendra la taille réelle de l'adresse homologue.

    répondre
    0
  • Annulerrépondre