2009-02-22 56 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