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 */ }}
- UNP函数笔记十七: 客户/服务器程序设计范式
- UNP 客户/服务器 程序设计范式 笔记
- UNP学习笔记(第三十章 客户/服务器程序设计范式)
- 客户/服务器程序设计范式
- UNP函数笔记三: TCP客户/服务器程序示例
- 主题:客户/服务器程序设计范式
- 【UNIX网络编程】客户/服务器程序设计范式
- 客户/服务器程序设计范式(9类)
- 第30章 客户/服务器程序设计范式
- UNP服务器设计范式总结
- UNP函数笔记十: 守护进程和inetd超级服务器
- Unix网络编程代码 第30章 客户/服务器程序设计范式
- UNIX网络编程卷一:第三十章 客户/服务器程序设计范式
- 《UNIX网络编程 卷1》 笔记: 服务器程序设计范式
- UNIX网络编程卷1 服务器程序设计范式1 并发服务器,为每个客户请求fork一个进程
- UNIX网络编程卷1 服务器程序设计范式6 并发服务器,为每个客户请求创建一个线程
- UNP函数笔记十六: 线程
- UNP总结 Chapter 5 TCP客户/服务器程序实例
- 设计页面时可否“左右撇子”兼顾之?
- [Mark] netmap - a novel framework for fast packet I/O
- 初学者VS2005 .Net WebService使用(一)- 创建WebService 三步曲
- .NET 面试题总结 (附有参考答案) 第2部分
- 学习java第一天---------------java源文件的命名规则
- UNP函数笔记十七: 客户/服务器程序设计范式
- ubuntu手动安装jdk6
- xml一些基础知识
- 全面解读WM_NOTIFY
- c++ Builder中如何让程序只运行一个实例
- ubuntu安装netbeans方法及解决netbeans乱码方法
- LINUX下使用移动3G上网卡攻略
- scsi命令
- .NET 面试题总结 (附有参考答案) 第3部分