while (((connfd = accept(listenfd)) != -1){
if (fork() == 0) {
write(connfd, buffer ,strlen(buffer));
close(connfd);
}
}
大家好,我在OS上获得了一个考试样题。 假设我有一个使用上述代码处理多个客户端的TCP服务器。如问题中所述,其余代码应该有效。现在,每次客户端连接到此服务器时,它都会从中读取数据然后卡住。这个问题的正确答案是,它发生是因为服务器没有正确关闭与客户端的连接。
我不确定我是否完全得到它,不是
接近(插座)
足够? 就我而言,当一个插座被一侧关闭时,另一侧读取EOF并返回0.考虑到客户端在读取时卡住了,它不应该到达那个EOF并继续前进?
答案 0 :(得分:1)
fork()
将在子进程中返回0,并在父进程中返回正pid。因此,close(connfd);
仅在子进程中调用。
但是,父进程执行了accept
,它仍然保留了一个打开的文件描述符到套接字。它也需要关闭它。在关闭所有打开的文件描述符之前,不会关闭套接字。也就是说,你需要像
pid_t child_pid = fork();
if (child_pid == 0) {
write(connfd, buffer ,strlen(buffer));
close(connfd);
}
else if (child_pid > 0) {
// parent
close(connfd);
}
else {
// a fork error occurred, handle and remember to close(connfd)
}
答案 1 :(得分:0)
@ AnttiHaapala的回答。
发送内容后,不应立即关闭套接字。一旦数据排队就写入返回,并且在发送所有内容之前实际发生关闭。
万无一失的方法是使用graceful shutdown:
pid_t child_pid = fork();
if (child_pid == 0) {
write(connfd, buffer ,strlen(buffer));
shutdown(connfd, SD_SEND); // send an EOF condition
while (read(connfd, buffer, sizeof(buffer) > 0); // wait for the peer to close its side
close(connfd); // and actually close
}
else if (child_pid > 0) {
// parent
close(connfd); // direct close because no send is pending
}
else {
// a fork error occurred, handle and remember to close(connfd)
}