1000字范文,内容丰富有趣,学习的好帮手!
1000字范文 > unix网络编程各种TCP客户-服务器程序设计实例(三)

unix网络编程各种TCP客户-服务器程序设计实例(三)

时间:2021-09-06 18:38:15

相关推荐

unix网络编程各种TCP客户-服务器程序设计实例(三)

第五种 TCP预先派生子进程服务器程序:

对预先派生子进程服务器的最后一种改动就是由父进程调用accept,然后再将所接受的已连接描述字传递给子进程。父进程必须跟踪子进程的忙闲状态,以便给空闲子进程传递新的描述字。为每个子进程维护一个信息结构,用来管理各子进程。

在调用fork之前,先创建一个字节流管道(Unix域的字节流套接口),它是Unix域的字节流套接口。当子进程派生后,父进程关闭一个描述字(sockfd[1]),子进程关闭另一个描述字(sockfd[0]),此外,子进程将流管道的字节所在端(sockfd[1])复制到标准输出。

child.h:

typedef struct {pid_tchild_pid;/* process ID */intchild_pipefd;/* parent's stream pipe to/from child */intchild_status;/* 0 = ready */longchild_count;/* # connections handled */} Child;Child*cptr;/* array of Child structures; calloc'ed */

Child.c:

/* include child_make */#include"unp.h"#include"child.h"Child*cptr;/* array of Child structures; calloc'ed */pid_tchild_make(int i, int listenfd, int addrlen){intsockfd[2];pid_tpid;voidchild_main(int, int, int);Socketpair(AF_LOCAL, SOCK_STREAM, 0, sockfd);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 */}Dup2(sockfd[1], STDERR_FILENO);/* child's stream pipe to parent */Close(sockfd[0]);Close(sockfd[1]);Close(listenfd);/* child does not need this open */child_main(i, listenfd, addrlen);/* never returns */}/* end child_make *//* include child_main */voidchild_main(int i, int listenfd, int addrlen){charc;intconnfd;ssize_tn;voidweb_child(int);printf("child %ld starting\n", (long) getpid());for ( ; ; ) {if ( (n = Read_fd(STDERR_FILENO, &c, 1, &connfd)) == 0)err_quit("read_fd returned 0");if (connfd < 0)err_quit("no descriptor from read_fd");web_child(connfd);/* process request */Close(connfd);Write(STDERR_FILENO, "", 1);/* tell parent we're ready again */}}/* end child_main */

pr_cpu_time.c:

#include"unp.h"#include<sys/resource.h>#ifndefHAVE_GETRUSAGE_PROTOintgetrusage(int, struct rusage *);#endifvoidpr_cpu_time(void){doubleuser, sys;struct rusagemyusage, childusage;if (getrusage(RUSAGE_SELF, &myusage) < 0)err_sys("getrusage error");if (getrusage(RUSAGE_CHILDREN, &childusage) < 0)err_sys("getrusage error");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);}

web_child.c:

#include"unp.h"#defineMAXN16384/* max # bytes client can request */voidweb_child(int sockfd){intntowrite;ssize_tnread;charline[MAXLINE], result[MAXN];for ( ; ; ) {if ( (nread = Readline(sockfd, line, MAXLINE)) == 0)return;/* connection closed by other end *//* 4line from client specifies #bytes to write back */ntowrite = atol(line);if ((ntowrite <= 0) || (ntowrite > MAXN))err_quit("client request for %d bytes", ntowrite);Writen(sockfd, result, ntowrite);}}

client.c:

#include"unp.h"#defineMAXN16384/* max # bytes to request from server */intmain(int argc, char **argv){inti, j, fd, nchildren, nloops, nbytes;pid_tpid;ssize_tn;charrequest[MAXLINE], reply[MAXN];if (argc != 6)err_quit("usage: client <hostname or IPaddr> <port> <#children> ""<#loops/child> <#bytes/request>");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]);Write(fd, request, strlen(request));if ( (n = Readn(fd, reply, nbytes)) != nbytes)err_quit("server returned %d bytes", n);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_sys("wait error");exit(0);}

server.c:

/* include serv05a */#include"unp.h"#include"child.h"static intnchildren;intmain(int argc, char **argv){intlistenfd, i, navail, maxfd, nsel, connfd, rc;voidsig_int(int);pid_tchild_make(int, int, int);ssize_tn;fd_setrset, masterset;socklen_taddrlen, 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);elseerr_quit("usage: serv05 [ <host> ] <port#> <#children>");FD_ZERO(&masterset);FD_SET(listenfd, &masterset);maxfd = listenfd;cliaddr = Malloc(addrlen);nchildren = atoi(argv[argc-1]);navail = nchildren;cptr = Calloc(nchildren, sizeof(Child));/* 4prefork 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);}Signal(SIGINT, sig_int);for ( ; ; ) {rset = masterset;if (navail <= 0)FD_CLR(listenfd, &rset);/* turn off if no available children */nsel = Select(maxfd + 1, &rset, NULL, NULL, NULL);/* 4check 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)err_quit("no available children");cptr[i].child_status = 1;/* mark child as busy */cptr[i].child_count++;navail--;n = Write_fd(cptr[i].child_pipefd, "", 1, connfd);Close(connfd);if (--nsel == 0)continue;/* all done with select() results */}/* 4find 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_quit("child %d terminated unexpectedly", i);cptr[i].child_status = 0;navail++;if (--nsel == 0)break;/* all done with select() results */}}}}/* end serv05a */voidsig_int(int signo){inti;voidpr_cpu_time(void);/* 4terminate 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_sys("wait error");pr_cpu_time();for (i = 0; i < nchildren; i++)printf("child %d, %ld connections\n", i, cptr[i].child_count);exit(0);}

编译命令:

gcc server.c child.c pr_cpu_time.c web_child.c -o server -lunp

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。