UNP函数笔记十七: 客户/服务器程序设计范式

来源:互联网 发布:安徽幻维网络是培训吗 编辑:程序博客网 时间:2024/05/21 15:05

第三十章  客户/服务器程序设计范式:


示例:

#include "err_exit.h"#include <sys/mman.h>/* * Allocate an array of "nchildren" longs in shared memory that can * be used as a counter by each child of how many clients it services. * See pp. 467-470 of "Advanced Programming in the Unix Environment." */long * meter(int nchildren){    int    fd;    long * ptr;#ifdef MAP_ANON    if ((ptr = mmap(0, nchildren*sizeof(long), PROT_READ | PROT_WRITE,                     MAP_ANON | MAP_SHARED, -1, 0)) == MAP_FAILED) {        err_exit("mmap error");    }#else    if ((fd = open("/dev/zero", O_RDWR, 0)) == -1) {        err_exit("open /dev/zero error");    }    if ((ptr = mmap(0, nchildren*sizeof(long), PROT_READ | PROT_WRITE,                     MAP_SHARED, fd, 0)) == MAP_FAILED) {        err_exit("mmap error");    }    Close(fd);#endif    return(ptr);}

#include "myio.h"#include "warp.h"#include "tcp_connect.h"#define MAXN 16384  /* max # bytes to request from server */int main(int argc, char ** argv){    int      i;    int      j;    int      fd;    int      nchildren;    int      nloops;    int      nbytes;    pid_t    pid;    ssize_t  n;    char     request[MAXLINE];    char     reply[MAXN];    if (argc != 6) {        printf("usage: client <hostname or IPaddr> <port> <#children> "               "<#loops/child> <#bytes/request>\n");        exit(1);    }    nchildren = atoi(argv[3]);    nloops = atoi(argv[4]);    nbytes = atoi(argv[5]);    snprintf(request, sizeof(request), "%d\n", nbytes);  /* newline at end */    for (i = 0; i < nchildren; i++) {        if ((pid = Fork()) == 0) {  /* child */            for (j = 0; j < nloops; j++) {                fd = tcp_connect(argv[1], argv[2]);                n = strlen(request);                if (write(fd, request, n) != n) {                    err_msg("write error", errno);                }                if ((n = readn(fd, reply, nbytes)) != nbytes) {                    err_msg("readn error", errno);                }                Close(fd);  /* TIME_WAIT on client, not server */            }            printf("child %d done\n", i);            exit(0);        }        /* parent loops around to fork() again */    }    while (wait(NULL) > 0) {  /* now parent waits for all children */    }    if (errno != ECHILD) {        err_msg("wait error", errno);    }    exit(0);}

#ifndef __READLINE_R_H__#define __READLINE_R_H__#include <stdio.h>#include <errno.h>#include <string.h>#include <stdlib.h>#ifndef MAXLINE#define MAXLINE 4096#endiftypedef struct {    int      read_fd;      /* caller's descriptor to read from */    char   * read_ptr;     /* caller's buffer to read into */    size_t   read_maxlen;  /* max #bytes to read */    int      rl_cnt;       /* initialize to 0 */    char   * rl_bufptr;    /* initialize to rl_buf */    char     rl_buf[MAXLINE];} Rline;ssize_t my_read_r(Rline * rptr, char * ptr){    if (rptr->rl_cnt <= 0) {again:        rptr->rl_cnt = read(rptr->read_fd, rptr->rl_buf, sizeof(rptr->rl_buf));        if (rptr->rl_cnt < 0) {            if (errno == EINTR) {                goto again;            }            else {                return(-1);            }        }        else if (rptr->rl_cnt == 0) {            return(0);        }        rptr->rl_bufptr = rptr->rl_buf;    }    rptr->rl_cnt--;    *ptr = *rptr->rl_bufptr++ & 255;    return(1);}void readline_rinit(int fd, void * ptr, size_t maxlen, Rline * rptr){    rptr->read_fd = fd;  /* save caller's arguments */    rptr->read_ptr = ptr;    rptr->read_maxlen = maxlen;    rptr->rl_cnt = 0;  /* and init our counter & pointer */    rptr->rl_bufptr = rptr->rl_buf;}ssize_t readline_r(Rline * rptr){    int    n;    int    rc;    char   c;     char * ptr;    ptr = rptr->read_ptr;    for (n = 1; n < rptr->read_maxlen; n++) {        if ((rc = my_read_r(rptr, &c)) == 1) {            *ptr++ = c;            if (c == '\n') {                break;            }        }        else if (rc == 0) {            if (n == 1) {                return(0);  /* EOF, no data read */            }            else {                break;  /* EOF, some data was read */            }        }        else {            return(-1);  /* error */        }    }    *ptr = 0;    return(n);}ssize_t Readline_r(Rline * rptr){    ssize_t n = readline_r(rptr);    if (n == -1) {        printf("readline_r error : %s\n", strerror(errno));    }    return(n);}#endif

#include "readline_r.h"#define MAXN 16384  /* max #bytes that a client can request */void web_child(int sockfd){    int      ntowrite;    ssize_t  nread;    char     line[MAXLINE];    char     result[MAXN];    Rline    rline;    readline_rinit(sockfd, line, MAXLINE, &rline);    for ( ; ; ) {        if ((nread = Readline_r(&rline)) == 0) {            return;  /* connection closed by other end */        }        /* line from client specifies #bytes to write back */        ntowrite = atol(line);        if ((ntowrite <= 0) || (ntowrite > MAXN)) {            printf("client request for %d bytes\n", ntowrite);            exit(1);        }        if (writen(sockfd, result, ntowrite) != ntowrite) {            printf("writen error : %s\n", strerror(errno));            exit(1);        }    }}

#include <stdio.h>#include <errno.h>#include <string.h>#include <stdlib.h>#include <sys/resource.h>void pr_cpu_time(void){    double         user;    double         sys;    struct rusage  myusage;    struct rusage  childusage;    if (getrusage(RUSAGE_SELF, &myusage) < 0) {        printf("getrusage error : %s\n", strerror(errno));        exit(1);    }    if (getrusage(RUSAGE_CHILDREN, &childusage) < 0) {        printf("getrusage error : %s\n", strerror(errno));        exit(1);    }    user = (double)myusage.ru_utime.tv_sec +                    myusage.ru_utime.tv_usec/1000000.0;    user += (double)childusage.ru_utime.tv_sec +                     childusage.ru_utime.tv_usec/1000000.0;    sys = (double)myusage.ru_stime.tv_sec +                   myusage.ru_stime.tv_usec/1000000.0;    sys += (double)childusage.ru_stime.tv_sec +                    childusage.ru_stime.tv_usec/1000000.0;    printf("\nuser time = %g, sys time = %g\n", user, sys);}

#include "myio.h"#include "warp.h"#include "my_signal.h"#include "tcp_listen.h"#include "web_child.h"#include "pr_cpu_time.h"void sig_int(int signo){    pr_cpu_time();    exit(0);}int main(int argc, char ** argv){    int               listenfd;    int               connfd;    socklen_t         clilen;    socklen_t         addrlen;    struct sockaddr * cliaddr;    if (argc == 2) {        listenfd = tcp_listen(NULL, argv[1], &addrlen);    }    else if (argc == 3) {        listenfd = tcp_listen(argv[1], argv[2], &addrlen);    }    else {        printf("usage: %s [ <host> ] <port#>\n", argv[0]);        exit(1);    }    cliaddr = Malloc(addrlen);    if (my_signal(SIGINT, sig_int) == SIG_ERR) {        err_msg("my_signal error", errno);    }    for ( ; ; ) {        clilen = addrlen;        connfd = Accept(listenfd, cliaddr, &clilen);        web_child(connfd);  /* process the request */        Close(connfd);  /* parent closes connected socket */    }}

#include "myio.h"#include "warp.h"#include "my_signal.h"#include "tcp_listen.h"#include "web_child.h"#include "pr_cpu_time.h"void sig_int(int signo){    pr_cpu_time();    exit(0);}void sig_chld(int signo){    pid_t  pid;    int    stat;    while ((pid = waitpid(-1, &stat, WNOHANG)) > 0) {        /* printf("child %d terminated\n", pid); */    }    return;}int main(int argc, char ** argv){    int               listenfd;    int               connfd;    pid_t             childpid;    socklen_t         clilen;    socklen_t         addrlen;    struct sockaddr * cliaddr;    if (argc == 2) {        listenfd = tcp_listen(NULL, argv[1], &addrlen);    }    else if (argc == 3) {        listenfd = tcp_listen(argv[1], argv[2], &addrlen);    }    else {        printf("usage: %s [ <host> ] <port#>\n", argv[0]);        exit(1);    }    cliaddr = Malloc(addrlen);    if (my_signal(SIGCHLD, sig_chld) == SIG_ERR) {        err_msg("my_signal error", errno);    }    if (my_signal(SIGINT, sig_int) == SIG_ERR) {        err_msg("my_signal error", errno);    }    for ( ; ; ) {        clilen = addrlen;        if ((connfd = accept(listenfd, cliaddr, &clilen)) < 0) {            if (errno == EINTR) {                continue;  /* back to for() */            }            else {                err_msg("accept error", errno);                exit(1);            }        }        if ((childpid = Fork()) == 0) {  /* child process */            Close(listenfd);  /* close listening socket */            web_child(connfd);  /* process request */            exit(0);        }        Close(connfd);  /* parent closes connected socket */    }}

#include "myio.h"#include "warp.h"#include "my_signal.h"#include "tcp_listen.h"#include "web_child.h"#include "pr_cpu_time.h"int     nchildren;pid_t * pids;void sig_int(int signo){    int  i;    /* terminate all children */    for (i = 0; i < nchildren; i++) {        kill(pids[i], SIGTERM);    }    while (wait(NULL) > 0) {  /* wait for all children */        }    if (errno != ECHILD) {        err_msg("wait error", errno);    }    pr_cpu_time();    exit(0);}void child_main(int i, int listenfd, int addrlen){    int               connfd;    socklen_t         clilen;    struct sockaddr * cliaddr;    cliaddr = Malloc(addrlen);    printf("child %ld starting\n", (long)getpid());    for ( ; ; ) {        clilen = addrlen;        connfd = Accept(listenfd, cliaddr, &clilen);        web_child(connfd);  /* process the request */        Close(connfd);    }}pid_t child_make(int i, int listenfd, int addrlen){    pid_t  pid;    if ((pid = Fork()) > 0) {        return(pid);  /* parent */    }    child_main(i, listenfd, addrlen);  /* never returns */}int main(int argc, char ** argv){    int        listenfd;    int        i;    socklen_t  addrlen;    if (argc == 3) {        listenfd = tcp_listen(NULL, argv[1], &addrlen);    }    else if (argc == 4) {        listenfd = tcp_listen(argv[1], argv[2], &addrlen);    }    else {        printf("usage: %s [ <host> ] <port#> <#children>\n", argv[0]);        exit(1);    }    nchildren = atoi(argv[argc-1]);    pids = Calloc(nchildren, sizeof(pid_t));    for (i = 0; i < nchildren; i++) {        pids[i] = child_make(i, listenfd, addrlen);  /* parent returns */    }    if (my_signal(SIGINT, sig_int) == SIG_ERR) {        err_msg("my_signal error", errno);    }    for ( ; ; ) {        pause();  /* everything done by children */    }}

#include "myio.h"#include "warp.h"#include "my_signal.h"#include "tcp_listen.h"#include "web_child.h"#include "pr_cpu_time.h"int     nchildren;pid_t * pids;struct flock  lock_it;struct flock  unlock_it;int    lock_fd = -1;  /* fcntl() will fail if my_lock_init() not called */void my_lock_init(char * pathname){    char  lock_file[1024];    /* must copy caller's string, in case it's a constant */    strncpy(lock_file, pathname, sizeof(lock_file));    if ((lock_fd = mkstemp(lock_file)) == -1) {        printf("mkstemp error : %s\n", strerror(errno));        exit(1);    }    if (unlink(lock_file) == -1) {  /* but lock_fd remains open */        printf("unlink error : %s\n", strerror(errno));        exit(1);    }    lock_it.l_type = F_WRLCK;    lock_it.l_whence = SEEK_SET;    lock_it.l_start = 0;    lock_it.l_len = 0;    unlock_it.l_type = F_UNLCK;    unlock_it.l_whence = SEEK_SET;    unlock_it.l_start = 0;    unlock_it.l_len = 0;}void my_lock_wait(){    while (fcntl(lock_fd, F_SETLKW, &lock_it) == -1) {        if (errno == EINTR) {            continue;        }        else {            printf("fcntl error for my_lock_wait\n");            exit(1);        }    }}void my_lock_release(){    if (fcntl(lock_fd, F_SETLKW, &unlock_it) == -1) {        printf("fcntl error for my_lock_release\n");        exit(1);    }}void child_main(int i, int listenfd, int addrlen){    int               connfd;    socklen_t         clilen;    struct sockaddr * cliaddr;    cliaddr = Malloc(addrlen);    printf("child %ld starting\n", (long)getpid());    for ( ; ; ) {        clilen = addrlen;        my_lock_wait();        connfd = Accept(listenfd, cliaddr, &clilen);        my_lock_release();        web_child(connfd);  /* process the request */        Close(connfd);    }}pid_t child_make(int i, int listenfd, int addrlen){    pid_t  pid;    if ((pid = Fork()) > 0) {        return(pid);  /* parent */    }    child_main(i, listenfd, addrlen);  /* never returns */}void sig_int(int signo){    int  i;    /* terminate all children */    for (i = 0; i < nchildren; i++) {        kill(pids[i], SIGTERM);    }    while (wait(NULL) > 0) {  /* wait for all children */    }    if (errno != ECHILD) {        err_msg("wait error", errno);    }    pr_cpu_time();    exit(0);}int main(int argc, char ** argv){    int        listenfd;    int        i;    socklen_t  addrlen;    if (argc == 3) {        listenfd = tcp_listen(NULL, argv[1], &addrlen);    }    else if (argc == 4) {        listenfd = tcp_listen(argv[1], argv[2], &addrlen);    }    else {        printf("usage: %s [ <host> ] <port#> <#children>\n", argv[0]);        exit(1);    }    nchildren = atoi(argv[argc-1]);    pids = Calloc(nchildren, sizeof(pid_t));    my_lock_init("/tmp/lock.XXXXXX");  /* one lock file for all children */    for (i = 0; i < nchildren; i++) {        pids[i] = child_make(i, listenfd, addrlen);  /* parent returns */    }    if (my_signal(SIGINT, sig_int) == SIG_ERR) {        err_msg("my_signal error", errno);    }    for ( ; ; ) {        pause();  /* everything done by children */    }}

#include <fcntl.h>#include <sys/mman.h>#include "myio.h"#include "warp.h"#include "my_signal.h"#include "tcp_listen.h"#include "web_child.h"#include "pr_cpu_time.h"int     nchildren;pid_t * pids;pthread_mutex_t * mptr;  /* actual mutex will be in shared memory */void my_lock_init(char * pathname){    int                  fd;    int                  error;    pthread_mutexattr_t  mattr;    if ((fd = open("/dev/zero", O_RDWR, 0)) == -1) {        err_msg("open /dev/zero error", errno);    }    if ((mptr = mmap(0, sizeof(pthread_mutex_t), PROT_READ | PROT_WRITE,                     MAP_SHARED, fd, 0)) == MAP_FAILED) {        err_msg("mmap error", errno);    }    Close(fd);    if ((error = pthread_mutexattr_init(&mattr)) != 0) {        err_msg("pthread_mutexattr_init error", error);    }    if ((error = pthread_mutexattr_setpshared(&mattr,                      PTHREAD_PROCESS_SHARED)) != 0) { /* process lock */        err_msg("pthread_mutexattr_setpshared error", error);    }    if ((error = pthread_mutex_init(mptr, &mattr)) != 0) {        err_msg("pthread_mutex_init error", error);    }}void my_lock_wait(){    Pthread_mutex_lock(mptr);}void my_lock_release(){    Pthread_mutex_unlock(mptr);}void child_main(int i, int listenfd, int addrlen){    int               connfd;    socklen_t         clilen;    struct sockaddr * cliaddr;    cliaddr = Malloc(addrlen);    printf("child %ld starting\n", (long)getpid());    for ( ; ; ) {        clilen = addrlen;        my_lock_wait();        connfd = Accept(listenfd, cliaddr, &clilen);        my_lock_release();        web_child(connfd);  /* process the request */        Close(connfd);    }}pid_t child_make(int i, int listenfd, int addrlen){    pid_t  pid;    if ((pid = Fork()) > 0) {        return(pid);  /* parent */    }    child_main(i, listenfd, addrlen);  /* never returns */}void sig_int(int signo){    int  i;    /* terminate all children */    for (i = 0; i < nchildren; i++) {        kill(pids[i], SIGTERM);    }    while (wait(NULL) > 0) {  /* wait for all children */    }    if (errno != ECHILD) {        err_msg("wait error", errno);    }    pr_cpu_time();    exit(0);}int main(int argc, char ** argv){    int        listenfd;    int        i;    socklen_t  addrlen;    if (argc == 3) {        listenfd = tcp_listen(NULL, argv[1], &addrlen);    }    else if (argc == 4) {        listenfd = tcp_listen(argv[1], argv[2], &addrlen);    }    else {        printf("usage: %s [ <host> ] <port#> <#children>\n", argv[0]);        exit(1);    }    nchildren = atoi(argv[argc-1]);    pids = Calloc(nchildren, sizeof(pid_t));    my_lock_init(NULL);    for (i = 0; i < nchildren; i++) {        pids[i] = child_make(i, listenfd, addrlen);  /* parent returns */    }    if (my_signal(SIGINT, sig_int) == SIG_ERR) {        err_msg("my_signal error", errno);    }    for ( ; ; ) {        pause();  /* everything done by children */    }}

#include <unistd.h>#include "myio.h"#include "warp.h"#include "my_signal.h"#include "tcp_listen.h"#include "read_fd.h"#include "write_fd.h"#include "web_child.h"#include "pr_cpu_time.h"#define   max(a, b)       ((a) > (b) ? (a) : (b))typedef struct {    pid_t  child_pid;     /* process ID */    int    child_pipefd;  /* parent's stream pipe to/from child */    int    child_status;  /* 0 = ready */    long   child_count;   /* # connections handled */} Child;Child  * cptr;  /* array of Child structures; calloc'ed */int  nchildren;void child_main(int i, int listenfd, int addrlen){    char     c;    int      connfd;    ssize_t  n;    printf("child %ld starting\n", (long)getpid());    for ( ; ; ) {        if ((n = read_fd(STDERR_FILENO, &c, 1, &connfd)) < 0) {            err_msg("read_fd error", errno);        }        else if (n == 0) {            printf("read_fd returned 0\n");            exit(1);        }        if (connfd < 0) {            printf("no descriptor from read_fd\n");            exit(1);        }        web_child(connfd);  /* process request */        Close(connfd);        /* tell parent we're ready again */        if (write(STDERR_FILENO, "", 1) != 1) {            err_msg("write error", errno);        }    }}pid_t child_make(int i, int listenfd, int addrlen){    int    sockfd[2];    pid_t  pid;    if (socketpair(AF_LOCAL, SOCK_STREAM, 0, sockfd) == -1) {        err_msg("socketpair error", errno);    }    if ((pid = Fork()) > 0) {        Close(sockfd[1]);        cptr[i].child_pid = pid;        cptr[i].child_pipefd = sockfd[0];        cptr[i].child_status = 0;        return(pid);        /* parent */    }    /* child's stream pipe to parent */    if (dup2(sockfd[1], STDERR_FILENO) == -1) {        err_msg("dup2 error", errno);    }    Close(sockfd[0]);    Close(sockfd[1]);    Close(listenfd);  /* child does not need this open */    child_main(i, listenfd, addrlen);  /* never returns */}void sig_int(int signo){    int  i;    /* terminate all children */    for (i = 0; i < nchildren; i++) {        kill(cptr[i].child_pid, SIGTERM);    }    while (wait(NULL) > 0) {  /* wait for all children */    }    if (errno != ECHILD) {        err_msg("wait error", errno);    }    pr_cpu_time();    for (i = 0; i < nchildren; i++) {        printf("child %d, %ld connections\n", i, cptr[i].child_count);    }    exit(0);}int main(int argc, char ** argv){    int               listenfd;    int               i;    int               navail;    int               maxfd;    int               nsel;    int               connfd;    int               rc;    ssize_t           n;    fd_set            rset;    fd_set            masterset;    socklen_t         addrlen;    socklen_t         clilen;    struct sockaddr * cliaddr;    if (argc == 3) {        listenfd = tcp_listen(NULL, argv[1], &addrlen);    }    else if (argc == 4) {        listenfd = tcp_listen(argv[1], argv[2], &addrlen);    }    else {        printf("usage: %s [ <host> ] <port#> <#children>\n", argv[0]);        exit(1);    }    FD_ZERO(&masterset);    FD_SET(listenfd, &masterset);    maxfd = listenfd;    cliaddr = Malloc(addrlen);    nchildren = atoi(argv[argc-1]);    navail = nchildren;    cptr = Calloc(nchildren, sizeof(Child));    /* prefork all the children */    for (i = 0; i < nchildren; i++) {        child_make(i, listenfd, addrlen);  /* parent returns */        FD_SET(cptr[i].child_pipefd, &masterset);        maxfd = max(maxfd, cptr[i].child_pipefd);    }    if (my_signal(SIGINT, sig_int) == SIG_ERR) {        err_msg("my_signal error", errno);    }    for ( ; ; ) {        rset = masterset;        if (navail <= 0) {            FD_CLR(listenfd, &rset);  /* turn off if no available children */        }        if ((nsel = select(maxfd + 1, &rset, NULL, NULL, NULL)) == -1) {            err_msg("select error", errno);        }        /* check for new connections */        if (FD_ISSET(listenfd, &rset)) {            clilen = addrlen;            connfd = Accept(listenfd, cliaddr, &clilen);            for (i = 0; i < nchildren; i++) {                if (cptr[i].child_status == 0) {                    break;  /* available */                }            }            if (i == nchildren) {                printf("no available children\n");                exit(1);            }            cptr[i].child_status = 1;  /* mark child as busy */            cptr[i].child_count++;            navail--;            if ((n = write_fd(cptr[i].child_pipefd, "", 1, connfd)) < 0) {                err_msg("write_fd error", errno);            }            Close(connfd);            if (--nsel == 0) {                continue;  /* all done with select() results */            }        }        /* find any newly-available children */        for (i = 0; i < nchildren; i++) {            if (FD_ISSET(cptr[i].child_pipefd, &rset)) {                if ((n = read(cptr[i].child_pipefd, &rc, 1)) < 0) {                    err_msg("read error", errno);                }                else if (n == 0) {                    printf("child %d terminated unexpectedly\n", i);                    exit(1);                }                cptr[i].child_status = 0;                navail++;                if (--nsel == 0) {                    break;  /* all done with select() results */                }            }        }    }}

#include "myio.h"#include "warp.h"#include "my_signal.h"#include "tcp_listen.h"#include "web_child.h"#include "pr_cpu_time.h"void * doit(void * arg){    Pthread_detach(pthread_self());    web_child((int)arg);    Close((int)arg);    return(NULL);}void sig_int(int signo){    pr_cpu_time();    exit(0);}int main(int argc, char ** argv){    int               listenfd;    int               connfd;    pthread_t         tid;    socklen_t         clilen;    socklen_t         addrlen;    struct sockaddr * cliaddr;    if (argc == 2) {        listenfd = tcp_listen(NULL, argv[1], &addrlen);    }    else if (argc == 3) {        listenfd = tcp_listen(argv[1], argv[2], &addrlen);    }    else {        printf("usage: %s [ <host> ] <port#>\n", argv[0]);        exit(1);    }    cliaddr = (struct sockaddr *)Malloc(addrlen);    if (my_signal(SIGINT, sig_int) == SIG_ERR) {        err_msg("my_signal error", errno);    }    for ( ; ; ) {        clilen = addrlen;        connfd = Accept(listenfd, cliaddr, &clilen);        Pthread_create(&tid, NULL, &doit, (void *)connfd);    }}

#include "myio.h"#include "warp.h"#include "my_signal.h"#include "tcp_listen.h"#include "web_child.h"#include "pr_cpu_time.h"typedef struct {    pthread_t  thread_tid;    /* thread ID */    long       thread_count;  /* # connections handled */} Thread;Thread * tptr;  /* array of Thread structures; calloc'ed */int              listenfd;int              nthreads;socklen_t        addrlen;pthread_mutex_t  mlock = PTHREAD_MUTEX_INITIALIZER;void * thread_main(void * arg){    int               connfd;    socklen_t         clilen;    struct sockaddr * cliaddr;    cliaddr = Malloc(addrlen);    printf("thread %d starting\n", (int) arg);    for ( ; ; ) {        clilen = addrlen;        Pthread_mutex_lock(&mlock);        connfd = Accept(listenfd, cliaddr, &clilen);        Pthread_mutex_unlock(&mlock);        tptr[(int)arg].thread_count++;        web_child(connfd);  /* process request */        Close(connfd);    }}void thread_make(int i){    Pthread_create(&tptr[i].thread_tid, NULL, &thread_main, (void *)i);    return;   /* main thread returns */}void sig_int(int signo){    int  i;    pr_cpu_time();    for (i = 0; i < nthreads; i++) {        printf("thread %d, %ld connections\n", i, tptr[i].thread_count);    }    exit(0);}int main(int argc, char ** argv){    int  i;    if (argc == 3) {        listenfd = tcp_listen(NULL, argv[1], &addrlen);    }    else if (argc == 4) {        listenfd = tcp_listen(argv[1], argv[2], &addrlen);    }    else {        printf("usage: %s [ <host> ] <port#> <#threads>\n", argv[0]);        exit(1);    }    nthreads = atoi(argv[argc-1]);    tptr = Calloc(nthreads, sizeof(Thread));    for (i = 0; i < nthreads; i++) {        thread_make(i);  /* only main thread returns */    }    if (my_signal(SIGINT, sig_int) == SIG_ERR) {        err_msg("my_signal error", errno);    }    for ( ; ; ) {        pause();  /* everything done by threads */    }}

#include "myio.h"#include "warp.h"#include "my_signal.h"#include "tcp_listen.h"#include "web_child.h"#include "pr_cpu_time.h"typedef struct {    pthread_t  thread_tid;    /* thread ID */    long       thread_count;  /* # connections handled */} Thread;Thread * tptr;  /* array of Thread structures; calloc'ed */#define MAXNCLI  32int              clifd[MAXNCLI];int              iget;int              iput;pthread_mutex_t  clifd_mutex = PTHREAD_MUTEX_INITIALIZER;pthread_cond_t   clifd_cond = PTHREAD_COND_INITIALIZER;int              nthreads;void * thread_main(void * arg){    int  connfd;    printf("thread %d starting\n", (int)arg);    for ( ; ; ) {        Pthread_mutex_lock(&clifd_mutex);        while (iget == iput) {            Pthread_cond_wait(&clifd_cond, &clifd_mutex);        }        connfd = clifd[iget];  /* connected socket to service */        if (++iget == MAXNCLI) {            iget = 0;        }        Pthread_mutex_unlock(&clifd_mutex);        tptr[(int)arg].thread_count++;        web_child(connfd);  /* process request */        Close(connfd);    }}void thread_make(int i){    Pthread_create(&tptr[i].thread_tid, NULL, &thread_main, (void *)i);    return;   /* main thread returns */}void sig_int(int signo){    int  i;    pr_cpu_time();    for (i = 0; i < nthreads; i++) {        printf("thread %d, %ld connections\n", i, tptr[i].thread_count);    }    exit(0);}int main(int argc, char ** argv){    int               i;    int               listenfd;    int               connfd;    socklen_t         addrlen;    socklen_t         clilen;    struct sockaddr * cliaddr;    if (argc == 3) {        listenfd = tcp_listen(NULL, argv[1], &addrlen);    }    else if (argc == 4) {        listenfd = tcp_listen(argv[1], argv[2], &addrlen);    }    else {        printf("usage: %s [ <host> ] <port#> <#threads>\n", argv[0]);    }    cliaddr = Malloc(addrlen);    nthreads = atoi(argv[argc-1]);    tptr = Calloc(nthreads, sizeof(Thread));    iget = iput = 0;    /* create all the threads */    for (i = 0; i < nthreads; i++) {        thread_make(i);  /* only main thread returns */    }    if (my_signal(SIGINT, sig_int) == SIG_ERR) {        err_msg("my_signal error", errno);    }    for ( ; ; ) {        clilen = addrlen;        connfd = Accept(listenfd, cliaddr, &clilen);        Pthread_mutex_lock(&clifd_mutex);        clifd[iput] = connfd;        if (++iput == MAXNCLI) {            iput = 0;        }        if (iput == iget) {            printf("iput = iget = %d\n", iput); /* children too less to hold */            exit(1);        }        Pthread_cond_signal(&clifd_cond);        Pthread_mutex_unlock(&clifd_mutex);    }}

#include "myio.h"#include "warp.h"#include "my_signal.h"#include "tcp_listen.h"#include "web_child.h"#include "pr_cpu_time.h"typedef struct {    pthread_t  thread_tid;    /* thread ID */    long       thread_count;  /* #connections handled */} Thread;Thread  * tptr;  /* array of Thread structures; calloc'ed */int        listenfd;int        nthreads;socklen_t  addrlen;void * thread_main(void * arg){    int               connfd;    socklen_t         clilen;    struct sockaddr * cliaddr;    cliaddr = Malloc(addrlen);    printf("thread %d starting\n", (int)arg);    for ( ; ; ) {        clilen = addrlen;        connfd = Accept(listenfd, cliaddr, &clilen);        tptr[(int)arg].thread_count++;        web_child(connfd);  /* process the request */        Close(connfd);    }}void thread_make(int i){    Pthread_create(&tptr[i].thread_tid, NULL, &thread_main, (void *)i);    return;  /* main thread returns */}void sig_int(int signo){    int  i;    pr_cpu_time();    for (i = 0; i < nthreads; i++) {        printf("thread %d, %ld connections\n", i, tptr[i].thread_count);    }    exit(0);}int main(int argc, char ** argv){    int  i;    if (argc == 3) {        listenfd = tcp_listen(NULL, argv[1], &addrlen);    }    else if (argc == 4) {        listenfd = tcp_listen(argv[1], argv[2], &addrlen);    }    else {        printf("usage: %s [ <host> ] <port#> <#threads>\n", argv[0]);        exit(1);    }    nthreads = atoi(argv[argc-1]);    tptr = Calloc(nthreads, sizeof(Thread));    for (i = 0; i < nthreads; i++) {        thread_make(i);  /* only main thread returns */    }    if (my_signal(SIGINT, sig_int) == SIG_ERR) {        err_msg("my_signal error", errno);    }    for ( ; ; ) {        pause();  /* everything done by threads */    }}


原创粉丝点击