我正在尝试套接字编程和服务器代码:
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)时, 代码运行正常。由于我要求一个新的子进程并关闭监听端口,为什么我得到一个错误的文件描述符?我在这里缺少什么。
答案 0 :(得分:1)
您关闭new_fd
两次。收到您关闭它之后,子进程将继续并再次关闭它。您应该将第二个close
仅放在父进程中,或者不要在if (fork())
正文中关闭。
答案 1 :(得分: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);
通过执行此操作,您可以在发送邮件后强制子进程立即关闭。我不完全确定,但我认为Bad文件描述符来自分叉子进程的调用,该进程尚未关闭但具有错误的文件描述符,因为您已关闭侦听套接字这个过程。