我正在编写一个服务器,当fork接受套接字连接时,fork()关闭子进程。
当孩子与客户沟通时,它必须将一些信息发送回父母。我正在使用烟斗来实现这一目标。
问题在于,当我尝试做父子IPC时,父母在读取孩子的输入时会阻止。这意味着,即使孩子们同时运行,他们也只能一次一个地处理,因为他们都在等待父母。
我的代码看起来像这样(为简洁起见,删除了错误检查):
/* loop: wait for clients to connect */
for(;;) {
pipe(write_to_parent); /* create pipe between parent and child */
pipe(write_to_child); /* create pipe between parent and child */
newsockfd = accept(...);
pid = fork();
if (pid == 0) { /* child process */
close(write_to_parent[0]);
close(write_to_child[1]);
printf("Connected!\n");
while ((rc = recv(newsockfd, ...)) > 0) {
/* process socket request */
/* write stuff to parent that is related to what we recv'd from client */
rc = write(write_to_parent[1], &buf, 1024);
}
printf("Disconnected!\n");
exit(0);
} else { /* parent */
close(write_to_parent[1]);
close(write_to_child[0]);
while (read(write_to_parent[0], &buf, 1024) > 0) {
/* accept data from child process, and do some processing */
}
}
}
所以我的问题是,我该如何解决这个问题?如何让父母使用管道与孩子进行沟通,使其不会阻塞?
管道是否可能,或者我应该使用共享内存(我猜是信号量)还是消息队列? (我读过这篇文章:Comparing Unix/Linux IPC但很难找到实际完成这些任务的例子。)
更多详情:
我有一个执行以下操作的测试程序: 1.连接到服务器 2.睡觉(5) 3.断开与服务器的连接
当我运行此程序的2个实例时,服务器输出:
connected!
// pause for 5 seconds
disconnected!
connected!
// pause for 5 seconds
disconnected!
显然每次处理一个客户端。
当我删除IPC时 - 当我从父级和子级中删除管道read()和write()时,我得到了这个:
connected!
connected!
// pause for 5ish seconds
disconnected!
disconnected!
这就是我想要的!
有关如何实现这一目标的任何想法? (或者我应该以解决这个问题的方式做出改变?)
(编辑:这是网络类任务的一部分。我们正在实施一个P2P协议,使用集中式服务器来管理同行。我们可以使用任何语言,我想我会给它一个旋转C。)
答案 0 :(得分:2)
我在下面写了答案,在重读你的问题时,注意到我完全错过了你的实际问题。但是,它在任何情况下都可能是有用的信息。
要回答您的并发父问题,您需要让父设置一个select()
循环来随时处理来自其任何子项的可能响应。你需要:
select()
的循环来接受传入连接(因为它们可能随时发生)以及来自任何子节点的传入数据waitpid()
收获已终止这项技术功能强大,但需要大量记账才能正确设置。
父进程中打开的文件句柄默认在子进程中继承。问题可能是两者父级和子级管道的写入端仍然打开,所以当父级从管道读取时,它将永远不会看到它的结束。在您开始阅读close(write_to_parent[1])
之前,请立即尝试在父级中使用write_to_parent[0]
。所以:
} else { /* parent */
close(write_to_parent[1]);
while (read(write_to_parent[0], &buf, 1024) > 0) {
/* accept data from child process, and do some processing */
}
}