2013-04-29 20 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,你可能会发现它更复杂,要获得良好的性能和随处可用。