cari

Rumah  >  Soal Jawab  >  teks badan

linux - Ralat program pelayan-pelanggan Program menerima isyarat SIGPIPE, Paip pecah.

Masukkan kod dahulu:

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

Keseluruhan aliran program adalah kira-kira seperti berikut:
Selepas pelayan dimulakan, Penerima berada dalam keadaan mendengar, dan kemudian pelanggan meminta sambungan Jika sambungan berjaya, pelayan memanggil panggilan balik newConnection untuk menghantar "apa khabar " kepada pelanggan, dan pelanggan mencetaknya selepas menerimanya.

Berikut ialah situasi ralat:
Menggunakan penyahpepijatan gdb, saya mendapati bahawa setiap kali ::write(sockfd, "how are you?n", 13);就会接收到SIGPIPE program mati.

Saya periksa Program terima signal SIGPIPE, Paip pecah.Sebabnya dikatakan menulis kepada sockfd tidak sah (tidak bersambung atau terputus). Tetapi apabila program saya berjalan ke penulisan fungsi panggil balik, sambungan tidak ditutup. (Untuk penyahpepijatan, saya juga mengulas penutup yang muncul dalam semua kod)

Selain itu, semasa menyahpepijat gdb untuk menulis, saya juga menggunakan ll /proc/pid/fd untuk menyemak deskriptor pekerjaan sistem semasa, dan connfd masih wujud.

Jadi saya tidak faham kenapa ada SIGPIPE sama sekali, tolong beri saya nasihat!

仅有的幸福仅有的幸福2749 hari yang lalu760

membalas semua(1)saya akan balas

  • 我想大声告诉你

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

    Selesai, sebabnya ialah parameter ketiga bagi ::accept tersilap lulus

    Dalam kod saya, pembungkus terima adalah seperti berikut:

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

    Kod panggilan ialah

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

    Ralatnya ialah parameter ketiga bagi ::accpet hendaklah melepasi saiz sockaddr_in asal dan bukannya saiz sockaddr yang ditukar. Diubah suai seperti berikut:

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

    Siarkanman 2 accept:

    Argumen addrlen ialah argumen hasil nilai: pemanggil mesti memulakannya untuk mengandungi saiz (dalam bait) struktur yang ditunjuk oleh addr; apabila dikembalikan, ia akan mengandungi saiz sebenar alamat rakan sebaya.

    balas
    0
  • Batalbalas