0

我正在尝试套接字编程和服务器代码:

    while(1) {
    sin_size = sizeof (their_addr);
    new_fd = accept(sockfd,(struct sockaddr *)&their_addr, &sin_size);
    if(new_fd == -1) {
        perror("accept");
        continue;
    }

    inet_ntop(their_addr.ss_family, get_in_addr((struct sockaddr*)&their_addr),s,sizeof(s));
    cout<<"got connection from" << s << endl;

    if((pid = fork()) == 0){//child
        close(sockfd);
        if(send(new_fd,"hello world!",12,0) == -1) {
            perror("send");
            close(new_fd);
            exit(0);
        }
        char buf[50];
        int numbytes;
        if((numbytes = recv(new_fd,&buf,50,0)) == -1) {
            perror("receive");
            close(new_fd);
            exit(0);
        }
        buf[numbytes] = '\0';
        cout<<"numbytes" << numbytes <<endl;
        cout<<"server received " << buf <<endl;
    }
    close(new_fd);
}

这段代码给了我一个错误的文件描述符,但是当我评论关闭(sockfd)时,代码运行良好。由于我正在分叉到一个新的子进程并关闭侦听端口,为什么我得到一个错误的文件描述符?有什么我在这里想念的吗。

4

2 回答 2

1

你关闭new_fd 两次。收到后关闭它一次,然后子进程继续并再次关闭它。您应该close仅将其放在父进程中,或者根本不在if (fork())正文中关闭。

于 2013-02-23T05:09:46.167 回答
1

我知道这个问题提出已经快 2 年了,但我遇到了同样的问题,在谷歌搜索并没有找到任何东西后,我决定尝试一段时间。我发现问题在于除非出现发送错误,否则您不会关闭子进程。所以不要这样:

if (send(new_fd,"hello world!",12,0) == -1) {
    perror("send");
    close(new_fd);
    exit(0);
}

将右括号移动到 perror 的正下方,如下所示:

if (send(new_fd,"hello world!",12,0) == -1) {
    perror("send");
}    
close(new_fd);
exit(0);

通过这样做,您可以强制子进程在发送消息后立即关闭。我不完全确定,但我认为错误的文件描述符来自分叉子进程对接受的调用,该子进程尚未关闭但具有错误的文件描述符,因为您已经关闭了侦听套接字这个过程。

于 2015-02-17T15:08:51.877 回答