The UNIX Operating System

TOP

UP


Ray Seyfarth

ORCA


Computer Science

COST

USM




Example Super Server


    struct service {
        char    *sv_name;
        char    sv_useTCP;
        int     sv_sock;
        int     (*sv_func)(int);
    };
    
    struct service svent[] = {
        { "echo", TCP_SERV, NOSOCK, TCPechod },
        { "chargen", TCP_SERV, NOSOCK, TCPchargend },
        { "daytime", TCP_SERV, NOSOCK, TCPdaytimed },
        { "time", TCP_SERV, NOSOCK, TCPtimed },
        { 0, 0, 0, 0 },
    };
    
    int main(int argc, char *argv[])
    {
        struct service  *psv,       /* service table pointer    */
                *fd2sv[NOFILE];     /* map fd to service pointer    */
        int     fd, nfds;
        fd_set  afds, rfds;         /* readable file descriptors    */
    
        nfds = 0;
        FD_ZERO(&afds);
        for (psv = &svent[0]; psv->sv_name; ++psv) {
            if (psv->sv_useTCP)
                psv->sv_sock = passiveTCP(psv->sv_name, QLEN);
            else
                psv->sv_sock = passiveUDP(psv->sv_name);
            fd2sv[psv->sv_sock] = psv;
            nfds = MAX(psv->sv_sock+1, nfds);
            FD_SET(psv->sv_sock, &afds);
        }
        (void) signal(SIGCHLD, reaper);
    
        while (1) {
            memcpy(&rfds, &afds, sizeof(rfds));
            if (select(nfds, &rfds, (fd_set *)0, (fd_set *)0,
                (struct timeval *)0) < 0) {
                if (errno == EINTR) continue;
                errexit("select error: %s\n", strerror(errno));
            }
            for (fd=0; fd<nfds; ++fd) {
                if (FD_ISSET(fd, &rfds)) {
                    psv = fd2sv[fd];
                    if (psv->sv_useTCP) doTCP(psv);
                    else psv->sv_func(psv->sv_sock);
                }
            }
        }
    }
    
    /*------------------------------------------------------------------------
     * doTCP - handle a TCP service connection request
     *------------------------------------------------------------------------
     */
    void doTCP(struct service *psv)
    {
        struct sockaddr_in fsin;    /* the request from address     */
        int     alen;               /* from-address length      */
        int     fd, ssock;
    
        alen = sizeof(fsin);
        ssock = accept(psv->sv_sock, (struct sockaddr *)&fsin, &alen);
        if (ssock < 0)
            errexit("accept: %s\n", strerror(errno));
        switch (fork()) {
        case 0: 
            break;
        case -1:
            errexit("fork: %s\n", strerror(errno));
        default:
            (void) close(ssock);
            return;     /* parent */
        }
        /* child */
    
        for (fd = NOFILE; fd >= 0; --fd)
            if (fd != ssock) (void) close(fd);
    
        exit(psv->sv_func(ssock));
    }
    
    /*------------------------------------------------------------------------
     * reaper - clean up zombie children
     *------------------------------------------------------------------------
     */
    void reaper(int sig)
    {
        int     status;
    
        while (wait3(&status, WNOHANG, (struct rusage *)0) >= 0)
                /* empty */;
    }
    


University of Southern Mississippi
Ray.Seyfarth@usm.edu
Updated 20:05 Jun 5, 2000