Re: Programming technique for non-forking servers?

From: Terry Lambert <terry@dont-contact.us>
Date: Wed, 13 Nov 1996 12:38:09 -0700 (MST)

> can anyone point me to some book, or URL(s), where the
> programming technique for writing non-forking network server
> daemons is described in details? with caveats, non-obvious
> places...

The Stevens books cover it...

> Yes, there are sources, but I'd really like to read
> some general theory on the subject.

The general theory is that you change a blocking call into a non-blocking
call + a context switch.

In other words, it's state-machine based event driven multithreading.

 ,------> wait for packet
 | |
 | v
 | select() o-----------------------.
 | | socket A | socket B
 | v v
 | f(context A) f(context B)
 | \ /
 | \ /
 | \ /
 | \ /
 | \ /
 | v
 | o packet processing function f()
 | |
 | v
 | o any additional processing
 | |
 `------------------------'

In addition, the packet may be a connect() request from a remote client;
if so, you need to:

1) accept the connection to bind it to a local socket
2) add the socket to the list of fd's that the select is
        listening to
3) continue processing

so the main loop looks like:

        /*
         * init
         */
        create connect_socket for incoming connections
        post listen() on socket connect_socket
        init default fd_set default_read_mask to contain connect_socket
        set max_fd to connect_socket + 1
        initialize context_list to NULL

        /*
         * main loop
         */
        while( 1) {
                copy default_read_mask to real_read_mask
                select( max_fd, real_read_mask)
                /*
                 * if we got here, a socket event has occurred;
                 * real_read_mask will now contain the fd's
                 * (sockets) which you must do processing on.
                 */

                /* check for incoming connections, first thing*/
                if( FD_ISSET( connect_socket, &real_read_mask)) {
                        /* clear so we don't hit it in processing loop*/
                        FD_CLR( connect_socket, &real_read_mask)

                        /* generate default context for new connection*/
                        ctxp = new_context();
                        add_context( ctxp, context_list);
                        ctxp->state = 0;
                        ctxp->fd = accept( connect_socket)

                        /* accept events on this context*/
                        FD_SET(ctxp->fd, &default_read_mask)
                }

                /* process all contexts which aren't incoming connections*/
                for( ctxp = context_list; ctxp = ctxp->next) {
                        if( FD_ISSET( ctxp->fd, &real_read_mask)) {
                                handle_event( ctxp);
                        }
                }
        }

                                        Terry Lambert
                                        terry@lambert.org

---
Any opinions in this posting are my own and not those of my present
or previous employers.
Received on Wed Nov 13 1996 - 11:50:23 MST

This archive was generated by hypermail pre-2.1.9 : Tue Dec 09 2003 - 16:33:32 MST