我有一台服务器正在侦听tcp端口。当有传入连接时,它使用accept()
并使用fork()
生成子进程。客户端/子进程从连接中读取一些数据,并通过管道将其发送回服务器。在此之后,我想关闭连接。我试图在客户端流程中使用shutdown()
和close()
而没有太多运气。
我检查了shutdown()
和close()
的结果,他们都返回0.所以显然他们顺利运行。运行shutdown()
和close()
后,服务器会从子进程收到sigchld
。这是在一般情况下处理,但我更愿意在接收信号之前关闭连接。
关于如何做到这一点的任何建议将非常感激。
旁注close()
已被用于在整个服务器/客户端程序中关闭不需要的文件描述符和套接字,但现在我不确定这些是否实际上已关闭。
以下是两个代码段。
首先是程序服务器部分中的accept()
和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)
的评论后,但它没有解决我的问题。为清楚起见,我还在代码段中添加了该行。
答案 0 :(得分:1)
涉及三个过程:
客户端:连接到父级的侦听套接字。
侦听套接字的父:服务器进程,接受连接并将其移交给孩子。
子:服务器进程,通过已建立的连接与客户端进行通信。
建立的连接仅存在于the child
和the client
之间。 The parent
无法检测客户端套接字何时从任何一方关闭。
有两种方式可以通知the parent
the child
正在关闭连接并终止,要么抓住SIGCHLD
信号,要让the child
向{{1}发送消息例如,问题中提到的the parent
。
答案 1 :(得分:0)
这有点令人尴尬,但似乎问题不在于close()
或shutdown()
。 KlasLindbäck的评论和答案让我思考,我进行了一些实验,发现SIGCHLD
已发送,因为客户端实际上在子进程同时关闭了连接。
所以我的解决方案受到了KlasLindbäck的建议的启发。子进程通过前面提到的管道发送进程ID,父进程现在可以安全地忽略/阻止从此进程发送的SIGCHLD
。