1高并发服务器:多进程服务器
1多進程并發服務器
使用多進程并發服務器時要考慮以下幾點:
A.父最大文件描述個數(父進程中需要close關閉accept返回的新文件描述符)
B.系統內創建進程個數(和內存大小相關)
C.進程創建過多是否降低整體服務性能(進程調度)
2.案例說明
server.c,代碼如下:
| #include <stdio.h> #include <string.h> #include <netinet/in.h> #include <arpa/inet.h> #include <signal.h> #include <sys/wait.h> #include <sys/types.h> #include <arpa/inet.h> #include <ctype.h> #include <unistd.h> #include "wrap.h" ? #define MAXLINE 80 #define SERV_PORT 8000 ? void do_sigchild(int num) { ??? waitpid(0,NULL,WNOHANG); } ? int main(void) { ??? struct sockaddr_in servaddr,cliaddr; ??? socklen_t cliaddr_len; ??? int listenfd,connfd; ??? char buf[MAXLINE]; ??? //INET_ADDRSTRLEN是ip地址的最大長度,是系統定義的一個宏 ??? char str[INET_ADDRSTRLEN]; ??? int i,n; ??? pid_t pid; ? ??? struct sigaction newact; ??? newact.sa_handler = do_sigchild; ??? sigemptyset(&newact.sa_mask); ??? newact.sa_flags = 0; ??? //發信號 ??? sigaction(SIGCHLD,&newact,NULL); ? ??? //1.這里建立一個TCP的連接,因為是SOCK_STREAM的,表示的是TCP的 ??? listenfd = Socket(AF_INET,SOCK_STREAM,0); ??? //將seraddr內容清零 ??? bzero(&servaddr,sizeof(servaddr)); ??? servaddr.sin_family = AF_INET; ??? servaddr.sin_addr.s_addr = htonl(INADDR_ANY); ??? servaddr.sin_port = htons(SERV_PORT); ??? //2.綁定ip地址和端口號 ??? Bind(listenfd,(struct sockaddr *)&servaddr,sizeof(servaddr)); ??? //監聽,最多的可以是20個 ??? Listen(listenfd,20); ??? ??? printf("Accepting connections...\n"); ??? while(1) { ??????? cliaddr_len = sizeof(cliaddr_len); ??????? //connfd:這里才是后續進程需要用的文件描述符 ??????? //listenfd:已經不用里,可以被銷毀,這個程序是在子進程里面銷毀 ??????? connfd = Accept(listenfd,(struct sockaddr *)&cliaddr,&cliaddr_len); ? ??????? pid = fork(); ??????? if(pid ==0) { ??????????? if(pid == 0) { ??????????????? Close(listenfd); ??????????????? while(1) { ??????????????????? n = Read(connfd,buf,MAXLINE); ??????????????????? if(n == 0) { ????????????????? ??????printf("the other side has been closed.\n"); ??????????????????????? break; ??????????????????? } ??????????????????? printf("received from %s at PORT %d\n", ??????????????????????? inet_ntop(AF_INET,&cliaddr.sin_addr.s_addr,str,sizeof(str)), ?????? ?????????????????ntohs(cliaddr.sin_port)); ??????????????????? ??????????????????? for(i = 0; i< n; i++) { ??????????????????????? buf[i] = toupper(buf[i]); ??????????????????? } ??????????????????? Write(connfd,buf,n); ??????????????? } ??????????????? Close(connfd); ??????????????? return 0; ??????????? } else if(pid > 0) { ??????????????? Close(connfd); ??????????? } else { ??????????????? perr_exit("fork"); ??????????? } ??????? } ??? } } |
client.c
| #include <stdio.h> #include <string.h> #include <unistd.h> #include <netinet/in.h> #include <arpa/inet.h> #include "wrap.h" ? #define MAXLINE 80 #define SERV_PORT 8000 ? int main(int argc,char *argv[]) { ??? struct sockaddr_in servaddr; ??? char buf[MAXLINE]; ??? int sockfd,n; ? ??? sockfd = Socket(AF_INET,SOCK_STREAM,0); ? ??? bzero(&servaddr,sizeof(servaddr)); ??? servaddr.sin_family = AF_INET; ??? inet_pton(AF_INET,"127.0.0.1",&servaddr.sin_addr.s_addr); ??? servaddr.sin_port = htons(SERV_PORT); ? ??? Connect(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr)); ? ??? while(fgets(buf,MAXLINE,stdin) != NULL) { ??????? Write(sockfd,buf,strlen(buf)); ??????? n = Read(sockfd,buf,MAXLINE); ??????? if(n == 0) { ??????????? printf("the other side has ben closed.\n"); ??????? } else { ??????????? Write(STDOUT_FILENO,buf,n); ??????? } ??? } ? ??? Close(sockfd); ??? return 0; } |
wrap.h
| #ifndef __WRAP_H_ #define __WRAP_H_ ? void perr_exit(const char *s); int Accept(int fd, struct sockaddr *sa, socklen_t *salenptr); void Bind(int fd, const struct sockaddr *sa, socklen_t salen); void Connect(int fd, const struct sockaddr *sa, socklen_t salen); void Listen(int fd, int backlog); int Socket(int family, int type, int protocol); ssize_t Read(int fd, void *ptr, size_t nbytes); ssize_t Write(int fd, const void *ptr, size_t nbytes); void Close(int fd); ssize_t Readn(int fd, void *vptr, size_t n); ssize_t Writen(int fd, const void *vptr, size_t n); static ssize_t my_read(int fd, char *ptr); ssize_t Readline(int fd, void *vptr, size_t maxlen); ? #endif |
wrap.c
| #include <stdlib.h> #include <errno.h> #include <sys/socket.h> ? void perr_exit(const char *s) { ???????? perror(s); ???????? exit(1); } ? int Accept(int fd, struct sockaddr *sa, socklen_t *salenptr) { ???????? int n; ? again: ???????? if ( (n = accept(fd, sa, salenptr)) < 0) { ?????????????????? if ((errno == ECONNABORTED) || (errno == EINTR)) ??????????????????????????? goto again; ?????????????????? else ??????????????????????????? perr_exit("accept error"); ???????? } ???????? return n; } ? void Bind(int fd, const struct sockaddr *sa, socklen_t salen) { ???????? if (bind(fd, sa, salen) < 0) ?????????????????? perr_exit("bind error"); } ? void Connect(int fd, const struct sockaddr *sa, socklen_t salen) { ???????? if (connect(fd, sa, salen) < 0) ?????????????????? perr_exit("connect error"); } ? void Listen(int fd, int backlog) { ???????? if (listen(fd, backlog) < 0) ?????????????????? perr_exit("listen error"); } ? int Socket(int family, int type, int protocol) { ???????? int n; ? ???????? if ( (n = socket(family, type, protocol)) < 0) ?????????????????? perr_exit("socket error"); ???????? return n; } ? ssize_t Read(int fd, void *ptr, size_t nbytes) { ???????? ssize_t n; ? again: ???????? if ( (n = read(fd, ptr, nbytes)) == -1) { ?????????????????? if (errno == EINTR) ??????????????????????????? goto again; ?????????????????? else ??????????????????????????? return -1; ???????? } ???????? return n; } ? ssize_t Write(int fd, const void *ptr, size_t nbytes) { ???????? ssize_t n; ? again: ???????? if ( (n = write(fd, ptr, nbytes)) == -1) { ?????????????????? if (errno == EINTR) ??????????????????????????? goto again; ?????????????????? else ??????????????????????????? return -1; ???????? } ???????? return n; } ? void Close(int fd) { ???????? if (close(fd) == -1) ?????????????????? perr_exit("close error"); } ssize_t Readn(int fd, void *vptr, size_t n) { ???????? size_t? nleft; ???????? ssize_t nread; ???????? char?? *ptr; ? ???????? ptr = vptr; ???????? nleft = n; ???????? while (nleft > 0) { ?????????????????? if ( (nread = read(fd, ptr, nleft)) < 0) { ??????????????????????????? if (errno == EINTR) ???????? ??????????????????????????? nread = 0; ??????????????????????????? else ???????????????????????????????????? return -1; ?????????????????? } else if (nread == 0) ??????????????????????????? break; ? ?????????????????? nleft -= nread; ?????????????????? ptr += nread; ???????? } ???????? return n - nleft; } ? ssize_t Writen(int fd, const void *vptr, size_t n) { ???????? size_t nleft; ???????? ssize_t nwritten; ???????? const char *ptr; ? ???????? ptr = vptr; ???????? nleft = n; ???????? while (nleft > 0) { ?????????????????? if ( (nwritten = write(fd, ptr, nleft)) <= 0) { ??????????????????????????? if (nwritten < 0 && errno == EINTR) ???????????????????????????????????? nwritten = 0; ??????????????????????????? else ???????????????????????????????????? return -1; ?????????????????? } ? ?????????????????? nleft -= nwritten; ?????????????????? ptr += nwritten; ???????? } ???????? return n; } static ssize_t my_read(int fd, char *ptr) { ???????? static int read_cnt; ???????? static char *read_ptr; ???????? static char read_buf[100]; ? ???????? if (read_cnt <= 0) { again: ?????????????????? if ( (read_cnt = read(fd, read_buf, sizeof(read_buf))) < 0) { ??????????????????????????? if (errno == EINTR) ???????????????????????????????????? goto again; ??????????????????????????? return -1; ?????????????????? } else if (read_cnt == 0) ??????????????????????????? return 0; ?????????????????? read_ptr = read_buf; ???????? } ???????? read_cnt--; ???????? *ptr = *read_ptr++; ???????? return 1; } ? ssize_t Readline(int fd, void *vptr, size_t maxlen) { ???????? ssize_t n, rc; ???????? char??? c, *ptr; ? ???????? ptr = vptr; ???????? for (n = 1; n < maxlen; n++) { ?????????????????? if ( (rc = my_read(fd, &c)) == 1) { ??????????????????????????? *ptr++ = c; ??????????????????????????? if (c? == '\n') ???????????????????????????????????? break; ?????????????????? } else if (rc == 0) { ??????????????????????????? *ptr = 0; ??????????????????????????? return n - 1; ?????????????????? } else { ??????????????????????????? return -1; ??????? } ???????? } ???????? *ptr? = 0; ???????? return n; } |
運行結果(編譯server):
運行client端
?
?
?
?
?
總結
以上是生活随笔為你收集整理的1高并发服务器:多进程服务器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 倍力佳轮胎质量如何,中国什么地方
- 下一篇: 24v3A卡侬头(铝酸)四轮老年带步车充