1

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

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

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

3)池大小是动态的。如果空闲进程(不为客户端提供服务)的数量小于 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;
}
4

2 回答 2

3

这是一个设计或架构问题,过于宽泛,无法用代码给出明确的答案。

因此,您知道您希望在其自己的进程中为每个新连接提供服务。您的其他两个约束提出(至少)两个问题:

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

这个比较容易。这里最常见的设计是:

  • 每个工作人员继承监听套接字并执行自己的accept()
    工作人员可以互斥监听套接字,以便在任何给定时间只有一个准备好调用accept(),或者他们每个人都可以简单地调用accept()——但在那个万一提防雷霆万钧
  • 工作人员通过UNIX 文件描述符传递从其他进程接收已经接受()的连接。
    例如,参见这个SO question

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

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

您需要知道,不仅有多少工人还活着,还需要知道哪些工人处于空闲状态(“空闲”)。让父进程跟踪其子进程是一个明显的开始,但这并不能单独区分空闲的工作人员和忙碌的工作人员。你可以使用一个共享的、互斥的状态表,无论是文件还是共享内存?或者,也许每个孩子都通过 socketpair()(与文件描述符传递相同)将其状态传达给父母?

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

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

于 2013-04-29T17:43:24.703 回答
1

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

父进程需要跟踪有多少孩子在那里。您可以在等待的线程中执行此操作。这将等待一个孩子死去。(参见 man 2 wait for various flavor。)当进程数变得太大时,您可以发送一个信号,孩子们可以捕捉到该信号以正确终止。但是,我假设父进程不会派生更多的孩子,直到其中一些孩子死亡并且不会超额订阅“K”限制。

于 2013-04-28T20:26:24.493 回答