流程C的动态池

时间:2013-04-28 20:17:57

标签: c++ c linux unix

我在UNIX上用UNIX编写程序。我必须在套接字上编写客户端 - 服务器(TCP)程序。客户端发送一些信息和服务器答案。无论客户端发送或接收什么,因为我成功为其编写代码。但是最后一部分任务对我来说很难。

1)一个连接 - 一个子进程。

2)对于使用池中预运行进程的新连接。

3)池大小是dinamic。如果自由进程(不是服务客户端)的数量变得小于N - 应创建新进程,如果它变得超过K - “额外”进程必须终止

这是我的代码。每个连接都使用fork()创建新的子进程。每个连接都在新进程中运行。但是如何制作我上面说过的动态池呢? 请帮助,这非常重要!这是我应该做的最后一次。

服务器代码:

int main(int argc, char * argv[])
{
        int cfd;
        int listener = socket(AF_INET, SOCK_STREAM, 0); //create listiner 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);
        }

        return 0;
}

2 个答案:

答案 0 :(得分:3)

这是一个设计或架构问题,对于使用代码的明确答案而言过于宽泛。

因此,您知道您希望在自己的进程中为每个新连接提供服务。你的另外两个限制(至少)提出了两个问题:

首先,如何将新连接路由到N个已经在运行的工作人员之一?

这相对容易。这里最常见的设计是:

  • 每个worker 继承侦听套接字并执行自己的accept()
    工作人员可以互斥监听套接字,这样只有一个人可以在任何给定时间调用accept(),或者他们每个人都可以调用accept() - 但在这种情况下要小心the thundering herd
  • 工作人员通过 UNIX文件描述符传递接收来自其他进程的ed()ed连接 例如,请参阅此SO question

其次,我们如何确保 N - K 空闲工作进程可用?

这是一个更大的问题,你必须根据自己的舒适度和任何其他限制来回答。

您需要知道,不仅仅有多少工人还活着,而是哪些工人闲着(&#34;免费&#34;)。让父母进程跟踪其子女是一个明显的开始,但这并不能让闲散的工人与忙碌的工人区别开来。您可以使用共享的互斥状态表,文件还是共享内存?或者也许每个孩子通过socketpair()(与文件描述符传递相同)传递给父母的状态?

然后,如果由于某种原因你超过 K ,你如何安全地杀死一个空闲工人?信号?在同一个socketpair()上给出的命令?新闲工作者是否可以检查状态表是否自动终止,如果闲置将超过 K ?你如何从意外的工人终止中恢复(例如,SEGV)?等等。

Apache的MPM prefork模块在​​此问题空间中实现了一种可能的设计。您可能想咨询它以获取想法。

答案 1 :(得分:1)

您的代码似乎不满足条件编号2.您的进程池未预先运行。接受连接时会创建进程。一种解释是你会做一堆分叉,然后让分叉的进程等待接受。一个人会得到它,然后它会进行处理。

父进程需要跟踪有多少孩子。你可以在一个等待的线程中执行此操作。这将等待孩子死亡。 (请参阅man 2等待各种口味。)当进程数量变得太大时,您可以发送一个孩子可以捕获的信号以便正确终止。但是,我假设父进程不会分叉更多的子进程,直到其中一些人死亡并且不会超额认购'K'限制。