【发布时间】:2016-04-06 09:01:47
【问题描述】:
我正在用 C 语言编写一个简单的服务器/客户端程序,它侦听网络接口并接受客户端。每个客户端都在一个分叉的进程中处理。
我的目标是让父进程知道,一旦客户端与子进程断开连接。
目前我的主循环如下所示:
for (;;) {
/* 1. [network] Wait for new connection... (BLOCKING CALL) */
fd_listen[client] = accept(fd_listen[server], (struct sockaddr *)&cli_addr, &clilen);
if (fd_listen[client] < 0) {
perror("ERROR on accept");
exit(1);
}
/* 2. [process] Call socketpair */
if ( socketpair(AF_LOCAL, SOCK_STREAM, 0, fd_comm) != 0 ) {
perror("ERROR on socketpair");
exit(1);
}
/* 3. [process] Call fork */
pid = fork();
if (pid < 0) {
perror("ERROR on fork");
exit(1);
}
/* 3.1 [process] Inside the Child */
if (pid == 0) {
printf("[child] num of clients: %d\n", num_client+1);
printf("[child] pid: %ld\n", (long) getpid());
close(fd_comm[parent]); // Close the parent socket file descriptor
close(fd_listen[server]); // Close the server socket file descriptor
// Tasks that the child process should be doing for the connected client
child_processing(fd_listen[client]);
exit(0);
}
/* 3.2 [process] Inside the Parent */
else {
num_client++;
close(fd_comm[child]); // Close the child socket file descriptor
close(fd_listen[client]); // Close the client socket file descriptor
printf("[parent] num of clients: %d\n", num_client);
while ( (w = waitpid(-1, &status, WNOHANG)) > 0) {
printf("[EXIT] child %d terminated\n", w);
num_client--;
}
}
}/* end of while */
一切正常,我唯一的问题是(可能)由于阻塞 accept 调用。
当我连接到上述服务器时,会创建一个新的子进程并调用child_processing。
但是,当我与该客户端断开连接时,主父进程不知道它并且不输出printf("[EXIT] child %d terminated\n", w);
但是,当我在第一个客户端断开连接后与第二个客户端连接时,主循环能够最终处理while ( (w = waitpid(-1, &status, WNOHANG)) > 0) 部分并告诉我第一个客户端 已断开连接。
如果之后只有一个客户端连接和断开连接,我的主父进程将永远无法判断它是否断开连接。
有没有办法告诉父进程我的客户已经离开了?
更新
因为我是一个真正的 c 初学者,如果你在你的答案中提供一些简短的 sn-ps 会很好,这样我就可以真正理解它了 :-)
【问题讨论】:
-
使用线程。
fork()模型基本上已经过时了。 -
@EJP,
fork()绝不是过时的。请参阅下面的答案 - 他们实际上提供了一个 不可用 原生线程的解决方案。