Linux – Client-Server-Programmfehler. Programm hat Signal SIGPIPE empfangen, Pipe defekt.
仅有的幸福
仅有的幸福 2017-05-16 13:18:39
0
1
767

Geben Sie zunächst den Code ein:

//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;
}

Der gesamte Programmablauf ist ungefähr wie folgt:
Nachdem der Server gestartet ist, befindet sich der Akzeptor im Überwachungsstatus und der Client fordert eine Verbindung an. Wenn die Verbindung erfolgreich ist, ruft der Server den Rückruf newConnection auf, um „Wie geht es Ihnen?“ zu senden " an den Kunden, und der Kunde druckt es aus, nachdem er es akzeptiert hat.

Die folgende Fehlersituation ist:
Beim GDB-Debugging habe ich festgestellt, dass jedes Mal ::write(sockfd, "how are you?n", 13);就会接收到SIGPIPE das Programm abstürzt.

Ich habe überprüft: Programm hat Signal SIGPIPE empfangen, Pipe defekt.Der Grund soll darin liegen, dass in ein ungültiges (nicht verbundenes oder getrenntes) Sockfd geschrieben wird. Aber wenn mein Programm zum Schreiben der Rückruffunktion ausgeführt wird, wird die Verbindung nicht geschlossen. (Zum Debuggen habe ich auch den Abschluss auskommentiert, der in allen Codes erscheint)

Außerdem habe ich beim Debuggen von GDB zum Schreiben auch ll /proc/pid/fd verwendet, um den aktuellen Systembelegungsdeskriptor zu überprüfen, und connfd ist immer noch vorhanden.

Ich verstehe also nicht, warum es SIGPIPE überhaupt gibt, bitte gebt mir einen Rat!

仅有的幸福
仅有的幸福

Antworte allen(1)
我想大声告诉你

已解决,原因是::accept的第三个参数传错

我的代码中,accept wrapper如下:

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

调用代码为

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

错误应该是在于::accpet的第三个参数,传递的应该是原sockaddr_in的大小而不是转换后的sockaddr的大小。修改如下:

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

贴一个man 2 accept

The addrlen argument is a value-result argument: the caller must initialize it to contain the size (in bytes) of the structure pointed to by addr; on return it will contain the actual size of the peer address.

Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage