C 如何正确使用叉子的插座闭合?
我对如何正确关闭套接字文件描述符有疑问。假设服务器在接受新连接时会派生另一个过程。原始套接字文件描述符是C 如何正确使用叉子的插座闭合?,c,sockets,fork,C,Sockets,Fork,我对如何正确关闭套接字文件描述符有疑问。假设服务器在接受新连接时会派生另一个过程。原始套接字文件描述符是sockfd,新的套接字文件描述符是new\u sockfd sockfd = socket(...) bind(...); listen(...); while(1) { new_sockfd = accept(...); if(fork() == 0) { // Child process dosomething(...); } else { }
sockfd
,新的套接字文件描述符是new\u sockfd
sockfd = socket(...)
bind(...);
listen(...);
while(1) {
new_sockfd = accept(...);
if(fork() == 0) {
// Child process
dosomething(...);
}
else {
}
}
我的问题是,我们应该把
close(sockfd)
和close(new\u sockfd)
放在哪里。我在网站上看到过一些例子(“处理多个连接”),他们将close(sockfd)
放在if
块中,将close(new\u sockfd)
放在else
块中。但是,在fork之后,这两个进程不是并行运行吗?如果父进程关闭了新的\u sockfd
,是否会影响处理套接字的子进程?另外,如果子进程执行close(sockfd)
,这不会影响整个套接字程序吗?父进程应该关闭接受的套接字(在else
块中):它在子进程中保持打开状态,直到子进程处理完它,此时它应该发出自己的close。当进程分叉时,文件描述符在子进程中重复。但是,这些文件描述符彼此不同。关闭子级中的文件描述符不会影响父级中相应的文件描述符,反之亦然
在您的情况下,由于子进程需要接受的套接字
new\u sockfd
,而父进程继续使用侦听套接字sockfd
,因此子进程应该关闭(sockfd)
(在if
块中;这不会影响父进程),父进程应该关闭(new\u sockfd)
(在else
块中;这不会影响子对象)。父进程和子进程同时运行的事实并不影响这一点。@JosephMyers这是不正确的。文件描述符在两个进程中都是不同的。父进程应关闭接受的套接字:它在子进程中保持打开状态。@EJP我将进一步研究此问题,也许会返回详细信息。我更熟悉它BSD系统的说谎者,根据我的经验,编程服务器和shell以及分叉过程通常可以对文件描述符和相关资源是否被复制或共享进行更细粒度的控制。感谢您花时间发表评论并提示我重温我从经验中记得的内容。If实际上是父进程(您在注释中编写了子进程?)。父进程对fork的调用返回子进程的pid(并输入条件),子对象对fork的调用返回nil。就像父对象关闭已接受的套接字一样,子对象希望关闭正在侦听的套接字。嗨,EJP,感谢您的友好回复。我仍然有点困惑,是不是因为fork还将复制另一个新的套接字连接,所以我们必须关闭每个文件描述符两次?我不太清楚为什么“它在子进程中保持打开状态,直到子进程完成”,因为这两个进程(父进程和子进程)并行运行时,新的\u sockfd可能会在子进程使用它之前被父进程关闭,对吗?@alk如果可能,最好使用SOCK\u CLOEXEC
创建侦听。Sig。FD是不同的。父进程关闭其套接字描述符,但套接字保持打开状态,直到子进程关闭其描述符*。或者相反根据@alk的评论,在监听套接字的情况下为nd。正如dbush随后的回答中所述。哦!现在我完全理解了这个概念。谢谢dbush:)@Jes没问题。如果它对您有用,请随时联系。