Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/57.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 这是关闭fork上套接字描述符的正确方法吗?_C_Sockets_Client Server_Fork_Tcpclient - Fatal编程技术网

C 这是关闭fork上套接字描述符的正确方法吗?

C 这是关闭fork上套接字描述符的正确方法吗?,c,sockets,client-server,fork,tcpclient,C,Sockets,Client Server,Fork,Tcpclient,考虑以下代码: socket_fd = start_server(port); while (1){ new_socket_fd = accept_client(socket_fd); int pid = fork(); if (pid == 0){ //I am the child server process close(socket_fd); <------(1) do_stuff_wit

考虑以下代码:

socket_fd = start_server(port);

while (1){

    new_socket_fd = accept_client(socket_fd);

    int pid = fork();

    if (pid == 0){

        //I am the child server process

        close(socket_fd);      <------(1)

        do_stuff_with_client(new_socket_fd, buffer);

        close(new_socket_fd);       <------(2)

        exit(0);

    } else if (pid > 0){

        //I am the parent server process

        close(new_socket_fd);      <------(3)

    } else {

        fprintf(stderr, "Fork error\n");
        return 1;
    }
}
socket\u fd=启动服务器(端口);
而(1){
新的\u套接字\u fd=接受客户端(套接字\u fd);
int-pid=fork();
如果(pid==0){
//我是子服务器进程
关闭(socket_fd);将注释流转换为答案

太长,读不下去了 是的。问题中的描述看起来是正确的,推理是正确的

在某种程度上,您的父进程应该等待已死亡的子进程,以防止僵尸的累积(但在子进程死亡之前它不应该阻止)。在循环中使用
WNOHANG
参数可能是合适的,在循环的父循环关闭
new\u socket\u fd
的部分。这可能会留下一个或多个僵尸,直到发出下一个传入请求。如果这是一个问题,您可以忽略
SIGCHLD
(因此永远不会创建僵尸),或者您可以安排定期唤醒,在此期间父进程检查僵尸

讨论

快速提问-那么父进程何时/何地关闭套接字

当父进程退出循环或被告知停止侦听套接字时,父进程将关闭
套接字。\u fd
。所示代码中没有这方面的实际规定,因此当父进程终止(或发生fork故障)时,它将关闭。关键是侦听套接字可用于许多连接-在完成侦听之前,您不希望在父级中关闭它

在这种情况下,因为这是一个无止境的循环,所以永远不会。服务器将始终侦听
listen(socket\u fd,N)
中定义的多达N个连接

请注意,
listen()
调用中的N参数是可排队等待侦听进程的未完成连接数。也就是说,尚未通过
accept()返回值的连接请求数
调用。这不是对
accept()
接受连接后可同时激活的连接数的限制

在孩子关闭
套接字\u fd
之前,绑定端口是否映射到两个PID?如果有传入数据包,它将被放入谁的队列

传入数据包与套接字的“打开文件描述”(或等效项-与“文件描述符”或“套接字描述符”不同)。无论是家长还是孩子,只要先读,都可以使用。类似地,传入的连接请求在
套接字_fd
上排队;家长或孩子都可以接受这些请求。但是,家庭已经同意由谁来做,这样他们就不会妨碍彼此

马特奥

我猜是父母的

阿杰

如果是这种情况,那么新的\u socket\u fd的数据包也会发生同样的情况,因为两个数据包都是打开的。这意味着在父节点关闭数据包之前,子节点将无法读取数据包。这可能会导致争用情况


这是基于误解。数据包通过文件描述符可供两个进程使用。当一个进程关闭文件描述符时,它将无法再访问发送到连接的信息(当然,也不能发送该连接上的数据)在那之前,除非参与者在谁读取数据、谁监听连接的问题上达成一致意见,否则只能靠抽签来判断

马特奥

但是文件描述符不应该在父级和子级之间产生干扰;这就是为什么关闭子级上的
socket\u fd
不会阻止父级侦听的原因

巴本

同意。但我认为你应该在while循环后关闭
插座\u fd
。万一明天你因某种情况而将循环更改为中断,你将冒着无故保持插座打开的风险

这是一种良好的做法,但循环不会退出(这是一个
而(1)
循环,故障模式会
从循环中返回
——在执行该操作之前,它可能会关闭套接字
返回
).如果程序退出,那么系统会关闭套接字,因此这并不重要,因为关闭打开的内容是一种良好的内务管理

阿杰

父级和子级中的文件描述符都不同。因此关闭一个描述符不应影响另一个描述符。但两个副本具有相同的4元组(src-ip、src-port、dest-ip、dest-port),因此具有此类头的数据包会去哪里

描述符不同,但它们所指的套接字连接是相同的。数据包可用于任何读取它的进程-父进程或子进程

马特奥

在我的示例中,
accept\u client
为客户机创建了
sockaddr
结构,因此4元组转到孩子的
new\u socket\u fd

这不太准确。首先,
accept\u client()
在有子函数之前调用;
new\u socket\u fd
仅在该函数完成时位于父函数中。第二,在
fork()之后
,这两个进程都可以访问
新的\u socket\u fd
,并且都可以读取客户端进程发送的数据。但是,该程序的设计使服务器能够在子进程在
新的\u socket\u fd
上处理传入的连接时重新侦听更多的连接请求,这是一种合理的分工。

请注意,允许父进程监听请求,子进程继续监听。但是,这与约定相反。这意味着“守护进程”进程监听会在每个连接请求上更改PID,从而难以确定当前正在套接字上监听的进程。传统方法代码中使用的是守护进程在很长一段时间内保持不变,因此记录PID以供以后的进程控制(杀死守护进程)是明智的