1

I'm writing program in UNIX on C. I have to write client-server(TCP) program on sockets. Client sends some information and server answer. No matter what client sends or receives because I successfully wrote code for it. But last part of task is very hard for me.

1)One connection - one child process.

2)For new connections using pre-running processes from a pool.

3)Pool size is dinamic.If the number of free processes(which is not servicing client) became less than N - should create new processes, if it became more than K - "extra" processes must be terminated.

This is my code. Every connection make new child process using fork().Each connection runs in new process. But how to make dynamic pool that I said above?
Please, help, it's very important! This is the last what I should do.

Server Code:

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;
}
Daniel Fischer
  • 181,706
  • 17
  • 308
  • 431
Nat Kup
  • 109
  • 3
  • 11
  • So, you need some sort of IPC between the parent and the children in the pool. Do you have any guidance on what IPC mechanism to use? `socketpair` maybe? – hyde Apr 28 '13 at 20:57
  • I read this yesterday and meant to get back to it. This is a bit trickier than the average student project. – Duck Apr 29 '13 at 20:20

2 Answers2

3

This is a design or architecture question, too broad for a definitive answer with code.

So, you know you want to service each new connection in its own process. Your other two constraints pose (at least) two questions:

First, how is a new connection routed to one of N already running workers?

This is comparatively easy. The most common designs here are:

  • Each worker inherits the listening socket and performs its own accept()
    The workers might mutex the listening socket, so that only one is ready to call accept() at any given time, or they might each simply call accept() — but in that case beware the thundering herd.
  • Workers receive already accept()ed connections from some other process via UNIX file descriptor passing.
    See, for instance, this SO question.

Second, how do we ensure that NK idle worker processes are available?

This is a larger question, one that you'll have to answer based on your comfort and any other constraints.

You need to know, not merely how many workers are alive, but which workers are idle ("free"). Having a parent process keep track of its children is an obvious start, but that won't distinguish idle workers from busy workers by itself. Could you use a shared, mutexed status table, either a file or in shared memory? Or perhaps each child communicates its status over a socketpair() — the same used for file descriptor passing — to the parent?

Then, how do you safely kill an idle worker if for some reason you exceed K? Signals? A command given over that same socketpair()? Can a newly-idle worker check the status table terminate itself if to go idle would exceed K? How do you recover from accidental worker termination (e.g., SEGV)? Etc. Etc.

Apache's MPM prefork module implements one possible design in this problem space. You may want to consult it for ideas.

Community
  • 1
  • 1
pilcrow
  • 56,591
  • 13
  • 94
  • 135
  • Thanks very much!!! Tomorrow I'll post my code with your advices, can you, please check it? – Nat Kup Apr 29 '13 at 19:26
  • 1
    There won't be a thundering herd. The kernel will guarantee only one child `accept` works and the others won't be aware. In any case this is not the way to go since it makes keeping track of the children and their state too hard. Having the parent do the accept and passing the descriptors is easier and then the domain sockets are in already in place to (a) pass busy/idle msgs to parent; (b) an "end yourself" msg from parent to idle children; (c) a convenient place for the children to block while waiting for work. – Duck Apr 29 '13 at 20:13
  • @Duck, just FYI, older linux kernels (~2.2.9?) were prone to a thundering herd with accept(). – pilcrow Apr 29 '13 at 20:37
  • 1
    @NatKup, if your new code has problems, post that here in a separate question. If you have a general question about your new code, post it on [codereview.SO](http://codereview.stackexchange.com). Thanks. – pilcrow Apr 30 '13 at 13:12
1

Your code doesn't seem to satisfy condition number 2. Your process pool is not pre-running. The processes are created when you accept the connection. One interpretation would have you do a bunch of forks and then have the forked processes wait for the accept. One would get it and then it would do the processing.

The parent process needs to keep track of how many children are out there. You could do this in a thread which does a wait. This will wait for a child to die. (see man 2 wait for various flavors.) When the number of processes becomes too big, you could send a signal which the children could catch in order to terminate properly. However, I am assuming that the parent process would NOT fork more children until some of them died and would not over-subscribe the 'K' limit.

No One in Particular
  • 2,846
  • 4
  • 27
  • 32