2

我有一台服务器正在侦听 tcp 端口。当有传入连接时,它使用accept()并使用fork(). 客户端/子进程从连接中读取一些数据并通过管道将其发送回服务器。在此之后,我想关闭连接。我曾尝试从客户端进程中使用shutdown()close()没有太多运气。

我检查了两者的结果,shutdown()它们close()都返回 0。所以显然它们运行顺利。在两者都运行之后shutdown()close()服务器sigchld从子进程接收到一个。这是在一般基础上处理的,但我更愿意在接收信号之前关闭连接。任何有关如何做到这一点的建议将不胜感激。

附带说明一下close(),已用于关闭整个服务器/客户端程序中不需要的文件描述符和套接字,但现在我不确定它们是否真的被关闭了。

下面是两个代码片段。首先是程序的服务器部分中的accept()and :fork()

if ((client_s = accept(s, &info.addr, &addrlen)) == -1) {
    //Error handling
}
if ((info.pid = fork()) == -1) {
    //More error handling
}
else if (info.pid == 0) {
    //Closing all unneeded file descriptors

    // Set default signal handler for SIGCHLD
    signal(SIGCHLD, SIG_DFL);

    _exit(clientStatus_main(client_s, info_pipes[1]));
}
else {
    //Adding client to list of clients and closing some file descriptors.
    close(client_s);
}

最后是来自函数 clientStatus_main 的代码片段:

//Signal handling
signal(SIGINT, client_sighandler);
signal(SIGTERM, client_sighandler);
signal(SIGKILL, client_sighandler);
signal(SIGHUP, client_sighandler);
signal(SIGCHLD, SIG_DFL);

//Read data from socket
read(socket, &status_packet.type, iLength)
//Do data handling and write back to server
write(info_pipe, &status_packet, status_packet.len)

//Close down socket
res = shutdown(socket, SHUT_RDWR);
addlog(LOG_INFO, "Result of shutdown: %i\n", res); //Write to log
res = close(socket);
addlog(LOG_INFO, "Result of close: %i\n", res);
return (iCount > 0 ? 0 : -1);

有什么好主意吗?

*编辑:在阅读了我试图close(client_s)从父进程中做的评论后,但它并没有解决我的问题。为清楚起见,我还在代码片段中添加了这一行。

4

2 回答 2

1

涉及三个过程:

客户端:连接到父级的监听套接字。

进程:侦听套接字、接受连接并将它们交给子进程的服务器进程。

child:通过已建立的连接与客户端对话的服务器进程。

建立的连接只存在于the child和之间the clientThe parent无法检测客户端套接字何时从任一侧关闭。

有两种方法可以通知the parent正在the child关闭连接和终止,要么捕获SIGCHLD信号,要么让the child发送消息到the parent,例如pipe问题中提到的。

于 2012-11-13T13:00:31.997 回答
0

这有点尴尬,但似乎问题不在于close()或根本不在于shutdown()。Klas Lindbäck 的评论和回答让我开始思考,我进行了一些实验,发现它SIGCHLD被发送是因为客户端实际上在子进程关闭连接的同时关闭了连接。

所以我的解决方案受到了 Klas Lindbäck 建议的启发。子进程通过前面提到的管道发送进程 ID,父进程现在可以安全地忽略/阻止SIGCHLD来自该进程的发送。

于 2012-11-14T09:08:29.930 回答