2013-04-29 21 views
0

我在Unix系統上用C編寫客戶端 - 服務器(TCP)程序。客戶端發送一些信息和服務器的答案。每個子進程只有一個連接。新的連接使用池中的預運行進程,並且池的大小是動態的,所以如果空閒進程的數量(不爲客戶端服務的進程)下降得太低,它應該創建新的進程,同樣如果額外的過高流程應該終止。進程的動態池

這是我的服務器代碼。每個連接使用fork()進行新的子進程。每個連接都在一個新的進程中運行。我如何製作像上面解釋過的動態泳池?

int main(int argc, char * argv[]) 
{ 
     int cfd; 
     int listener = socket(AF_INET, SOCK_STREAM, 0); //create listener socket 
     if(listener < 0){ 
      perror("socket error"); 
      return 1; 
     } 
     struct sockaddr_in addr; 
     addr.sin_family = AF_INET; 
     addr.sin_port = htons(PORT); 
     addr.sin_addr.s_addr = htonl(INADDR_ANY); 
     int binding = bind(listener, (struct sockaddr *)&addr, sizeof(addr)); 
     if(binding < 0){ 
      perror("binding error"); 
      return 1; 
     } 
     listen(listener, 1); //listen for new clients 
     signal(SIGCHLD,handler); 
     int pid; 

     for(;;) // infinity loop on server 
     { 
      cfd = accept(listener, NULL, NULL); //client socket descriptor 
      pid = fork(); //make child proc 
      if(pid == 0) //in child proc... 
      { 
       close(listener); //close listener socket descriptor 
       ... //some server actions that I do.(receive or send) 
       close(cfd); // close client fd 
       return 0; 
      } 
      close(cfd); 

}

回答

1

如果你已經封鎖幾個進程中accept同一偵聽套接字上,那是在一個新的連接將被傳遞到其中的一個。 (取決於,有幾個可能會醒來,但只有一個會真正獲得連接)。所以你需要在listen之後岔開幾個孩子,但之前需要accept。處理完請求後,孩子回到accept而不是exit。這處理(1)和(2)。 (3)較難。你需要某種形式的IPC。通常情況下,您將擁有一個父級流程,只需管理適當數量的子級。你的子進程需要使用IPC來告訴父母他們有多忙。然後家長可以分娩更多的孩子(進入上面的accept循環)或發送信號給孩子,告訴他們完成並退出。它也應該處理wait對孩子,處理意外死亡等。

你想使用的IPC可能是共享內存。您的兩個選項是SysV(shmget) and POSIX ( shm_open`)共享內存。如果可能,您可能需要後者。你將不得不處理同步訪問(POSIX和SysV都提供信號來幫助實現這一點,再次優先使用POSIX)或僅使用原子訪問。 (你可能實際上並不想要一個進程退出的時刻有超過X個免費的孩子,這將導致反覆收穫併產生它們,這是昂貴的。相反,你可能想要一些如何利用他們在最後一秒...所以你的數據比使用/免費的位圖更復雜。)

有很多守護程序可以像這樣工作,所以你可以很容易地找到代碼示例。當然,如果你看看Apache,你可能會發現它更復雜,要獲得良好的性能和隨處可用。