2009-02-22 32 views
1

我正在编写一个服务器,它在fork()接受套接字连接时关闭子进程。在C中为父 - 子IPC使用管道使程序块

当孩子与客户进行通信时,它必须将某些信息发回父母。我正在使用管道来完成此操作。

问题是,当我尝试做父母子女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 - 当我摆脱()读取管道和write()从父母和孩子双方的,我得到这样的:

connected! 
connected! 
    // pause for 5ish seconds 
disconnected! 
disconnected! 

这就是我想要的!

有关我如何完成此操作的任何想法? (或者我应该改变方式来解决这个问题?)

(编辑:这是一个网络类的任务的一部分,我们正在实现一个P2P协议,它使用一个集中的服务器来管理我可以使用任何语言,我想我会在C中给它一个旋风。)

回答

2

我在下面写了答案,并且在重读您的问题时,发现我完全错过了您的实际问题。但是,无论如何,这可能是有用的信息。

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

  • 跟踪有多少孩子是开放
  • 保持一套管道为每个孩子
  • 使用循环与select()既接受传入的连接(因为它们可能会发生在任何时候),也禁止任何儿童
  • 使用waitpid()谋取孩子谁已终止

该输入数据技术是强大的,但需要大量的簿记才能正确设置。


在父进程中打开的文件句柄默认在子进程中继承。问题可能是都是父级和子级的管道写端仍然打开,所以当父级从管道读取时,它永远不会看到它的结尾。在开始从write_to_parent[0]开始阅读之前,请立即尝试在家长中使用close(write_to_parent[1])。所以:

} 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 */ 
    } 
} 
+0

你说得对使用close()方法 - 我必须在我的代码,但我已经从这个片段中省略它完全是出于无心。不过,我已经添加了它。谢谢! – poundifdef 2009-02-22 19:59:33