linux - 客戶-伺服器程式錯誤Program received signal SIGPIPE, Broken pipe.
仅有的幸福
仅有的幸福 2017-05-16 13:18:39
0
1
721

先上程式碼:

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

整個程式流程大致如下:
server啟動之後Acceptor處於listen狀態,然後client請求連接,連接成功server就呼叫回呼newConnection發送「how are you」給client,client接受之後才印出來。

下面說下錯誤情況:
使用gdb調試發現每次在::write(sockfd, "how are you?\n", 13);就會接收到 SIGPIPE然後程式死掉。

查了一下Program received signal SIGPIPE, Broken pipe.的原因,都說是對無效(未連接或連接斷開)的sockfd進行write。但是我的程式運行到回呼函數的write時也沒有出現關閉連接的情況。 (為了調試我還把所有程式碼中出現的close都註解掉)

另外,gdb調試到write的時候,我還用ll /proc/pid/fd查看了當前系統佔用描述符,connfd也還存在著。

所以完全搞不懂為什麼還會有SIGPIPE,求指教!

仅有的幸福
仅有的幸福

全部回覆(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.

熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!