簡體   English   中英

錯誤的文件描述符:accept()錯誤

[英]bad file descriptor: error on accept()

我正在嘗試編寫一個簡單的聊天應用程序,其中客戶端從服務器接收字符串並發送新消息,該消息將傳遞到下一個連接的客戶端。 我是套接字編程的新手,但我真的不知道為什么會發生此錯誤。 客戶端發送緩沖區后,服務器會通知accept()錯誤(返回-1)和錯誤的文件描述符。 這是服務器上運行的代碼:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

void error(char *msg) {
    perror(msg);
    exit(1);
}

int main (int argc, char *argv[] ) {

    if ( argc < 2 ) {
        error("ERROR, no port provided\n");
    }

    int sockfd;
    struct sockaddr_in serv_addr, cli_addr;
    int cli_len, portno;
    char message[256];
    pid_t pid;
    int n;

    portno = atoi( argv[1] );
    bzero( (char*)&serv_addr, sizeof(serv_addr) );
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = INADDR_ANY;
    serv_addr.sin_port = htons( portno );

    sockfd = socket( AF_INET, SOCK_STREAM, 0 );

    n =  bind ( sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr) );
    if ( n < 0 ) {
        error("ERROR on binding\n");
    }

    listen( sockfd, 5 );

    do {
        cli_len = sizeof(cli_addr);

        int newsockfd;
        newsockfd = accept( sockfd,(struct sockaddr*)&cli_addr,(socklen_t *)&cli_len);
        if ( newsockfd < 0 ) {
            printf("%i", newsockfd);
            error("ERROR on accept\n");

        }

        pid = fork();
        if( pid == 0 ) {

            close( sockfd );
            sockfd = -1;

            n = send( newsockfd, message, strlen(message), 0);
            if ( n < 0 ) error("ERROR sending\n");

            bzero(message, 256);

            n = recv( newsockfd, message, 256, 0);
            if ( n < 0 ) error("ERROR receiving\n");

            close( newsockfd );
            newsockfd = -1;

        } 

    }
    while( 1 );

    return 0;
}

如果fork()的結果為零,則需要使用接受的套接字進行I / O, 然后退出process 目前,在關閉偵聽套接字后,您允許在子進程中重復執行accept循環。

分叉的孩子應該在read()之后結束,但是沒有結束。 它繼續循環。 可能不是您的意圖。

然后,子代調用accept()-1作為套接字描述符傳遞。 -1不是有效的套接字描述符。

    accept(sockfd, ...

孩子在這里將sockfd設置為-1

    pid = fork();
    if( pid == 0 ) {

        close( sockfd );
        sockfd = -1;

這樣做會丟失socket()返回的有效套接字描述符。

因此,您觀察到的錯誤不是由偵聽服務器進程引起的,而是由分叉的孩子引起的。

要解決此問題,請在孩子內部添加對exit()的調用,如下所示:

        ...
        newsockfd = -1;
        exit(EXIT_SUCCESS);
      }

int cli_len; 應該是socklen_t cli_len; 並且在調用accept()時應刪除cli_len 不要盲目拋棄錯誤!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM