1

我正在编写一个服务器,当它接受套接字连接时,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 */
       }
  }
}

所以我的问题是,我该如何解决这个问题?我怎样才能让父母使用管道与孩子进行交流,而不会阻塞?

这甚至可以通过管道实现,还是我应该使用共享内存(我猜是信号量)或消息队列?(我读过这篇文章:比较 Unix/Linux IPC,但很难找到这些任务是如何实际完成的示例。)

更多细节:

我有一个执行以下操作的测试程序: 1. 连接到服务器 2. Sleep(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 中试一试。)

4

1 回答 1

2

我在下面写了答案,并在重新阅读您的问题后,注意到我完全错过了您的实际问题。但是,在任何情况下它都可能是有用的信息。

要回答您并发的父级问题,您需要让父级设置一个select()循环来随时处理来自其任何子级的可能响应。您将需要:

  • 跟踪有多少孩子是开放的
  • 为每个孩子保留一组管道
  • 使用循环select()来接受传入的连接(因为它们可能随时发生)以及来自任何孩子的传入数据
  • 用来waitpid()收割已经终止的孩子

这种技术很强大,但确实需要大量的簿记才能正确设置。


默认情况下,在父进程中打开的文件句柄在子进程中继承。问题可能是父母和孩子的管道的写端仍然打开,所以当父母从管道读取时,它永远不会看到它的结束。close(write_to_parent[1])在开始阅读之前尝试在父母中使用 a 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 */
     }
}
于 2009-02-22T19:50:48.150 回答