1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > 几种并发服务器模型的实现:多线程 多进程 select poll epoll

几种并发服务器模型的实现:多线程 多进程 select poll epoll

时间:2019-11-14 07:00:53

相关推荐

几种并发服务器模型的实现:多线程 多进程 select poll epoll

/wj9012/p/3879605.html

客户端使用select模型:

1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #include <errno.h> 5 #include <sys/types.h> 6 #include <sys/socket.h> 7 #include <netinet/in.h> 8 #include <arpa/inet.h> 9 #include <sys/select.h> 10 #include <signal.h> 11 12 #define ERR_EXIT(m) \ 13do { \ 14 perror(m);\ 15 exit(EXIT_FAILURE);\ 16}while(0) 17 18 static void do_client(int fd) 19 { 20char recvbuf[MAXLINE + 1] = {0}; 21char sendbuf[MAXLINE + 1] = {0}; 22 23fd_set reade, ready; 24FD_ZERO(&reade); 25int fd_stdin = fileno(stdin); 26FD_SET(fd_stdin, &reade); 27FD_SET(fd, &reade); 28int fd_max = (fd_stdin > fd) ? fd_stdin : fd; 29 30int ret; 31while(1) 32{ 33 ready = reade; 34 ret = select( fd_max+1, &ready, NULL, NULL, NULL);//轮询 35 if(ret == -1) 36 { 37 if(errno == EINTR) 38 continue; 39 ERR_EXIT("select"); 40 }else if(ret == 0) 41 { 42 continue; 43 } 44 45 if(FD_ISSET(fd_stdin, &ready)) 46 { 47 if(fgets(sendbuf, sizeof(sendbuf), stdin) == NULL) 48 { 49 close(fd); 50break; 51 }else 52 { 53 if( -1 == write(fd, sendbuf, strlen(sendbuf))) 54 printf("write\n"); 55 } 56 } 57 58 59 if(FD_ISSET(fd, &ready)) 60 { 61 int nread = read(fd, recvbuf, MAXLINE); 62 if(nread < 0) 63 ERR_EXIT("read"); 64 if(nread == 0)//如果没接收到消息,打印关闭描述符,退出循环 65 { 66 fprintf(stdout, "fd close\n"); 67 break; 68 } 69 fprintf(stdout, "receive:%s", recvbuf); 70 } 71 memset(recvbuf, 0, sizeof recvbuf); 72 memset(sendbuf, 0, sizeof sendbuf); 73} 74 } 75 void handle(int signum) 76 { 77 printf("sigpipe\n"); 78 } 79 80 int main(int argc, const char *argv[]) 81 { 82signal(SIGPIPE, SIG_IGN); 83int fd = socket(AF_INET, SOCK_STREAM, 0); 84if(fd < 0) 85 ERR_EXIT("socket"); 86 87struct sockaddr_in cliaddr; 88cliaddr.sin_family = AF_INET; 89cliaddr.sin_port = htons(8888); 90cliaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); 91socklen_t len = sizeof cliaddr; 92 93int ret ; 94if((ret = connect(fd, (struct sockaddr*)&cliaddr, len)) == -1) 95{ 96 close(fd); 97 ERR_EXIT("connect"); 98} 99do_client(fd);100close(fd);101return 0;102 }

1.并发多进程服务器

2.多线程服务器模型:

3.select服务器模型:

1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #include <unistd.h> 5 #include <errno.h> 6 #include <sys/types.h> 7 #include <sys/stat.h> 8 #include <sys/socket.h> 9 #include <arpa/inet.h> 10 #include <signal.h> 11 #include <sys/select.h> 12 #define MAXLEN 1024 13 14 #define ERR_EXIT(m) \ 15do { \ 16 perror(m);\ 17 exit(EXIT_FAILURE);\ 18}while(0) 19 20 int listenf();//封装了网络socket的socekt,bind,listen函数,返回监听的socket描述符 21 void handle(int signum)//SIGPIPE(子进程结束)的信号的处理 22 { 23printf("hello\n"); 24 } 25 static void do_select(int); 26 27 int main(int argc, const char *argv[]) 28 { 29if(signal(SIGPIPE, handle) == SIG_ERR) 30 ERR_EXIT("signal"); 31int listenfd = listenf(); 32do_select(listenfd); 33close(listenfd); 34return 0; 35 } 36 37 int listenf() 38 { 39int listenfd = socket(AF_INET, SOCK_STREAM, 0);//准备一个socketfd 40if(listenfd == -1 ) 41 ERR_EXIT("listen"); 42 43int on = 1; 44if(setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1)//setsockopt设置端口复用 45{ 46 close(listenfd); 47 ERR_EXIT("setsockopt"); 48} 49 50struct sockaddr_in seraddr; 51seraddr.sin_family = AF_INET; 52seraddr.sin_port = htons(8888); 53seraddr.sin_addr.s_addr = htonl(INADDR_ANY); 54socklen_t len = sizeof(seraddr); 55if(bind(listenfd, (struct sockaddr*)&seraddr, len) == -1)//监听socket端口, 56{ 57 close(listenfd); 58 ERR_EXIT("bind"); 59} 60 61if(listen(listenfd, 6) == -1) 62{ 63 close(listenfd); 64 ERR_EXIT("listen"); 65} 66return listenfd; 67 } 68 69 void do_select(int fd) 70 { 71//struct sockaddr_in cliaddr; 72//memset(&cliaddr, 0, sizeof(cliaddr));//此处不需要客户端的地址信息 73fd_set set; 74fd_set rset; 75FD_ZERO(&rset); 76FD_SET(fd, &rset); 77int nready; 78int fd_set[MAXLEN]; 79 80int i; 81for(i = 0;i < MAXLEN; ++i) 82 fd_set[i] = -1; 83fd_set[0] = fd; 84 85int maxi = fd;//初始最大轮询fd是监听的fd 86int arrlen = 1;//表示数组长度 8788 char recvbuf[1024] = {0}; 89while(1) 90{ 91 set = rset; 92 nready = select(maxi+1, &set, NULL, NULL, NULL); 93 if(nready == -1) 94 { 95 ERR_EXIT("select"); 96 } 97 if(FD_ISSET(fd, &set))//查看书否有新的客户端请求 98 { 99 int clifd = accept(fd, NULL, NULL);100 if(clifd == -1)101 ERR_EXIT("accept");102 for(i = 1; i < MAXLEN; ++i)103 { if(fd_set[i] == -1)104 {105 fd_set[i] = clifd;106 break;107 }108 }109 FD_SET(clifd, &rset);110 if(clifd > maxi)111 maxi = clifd;112 arrlen++;113 --nready;114 }115 116 for(i = 1; i < arrlen; ++i)//轮询数据连接117 {118 int set_fd = fd_set[i];119if(FD_ISSET(set_fd, &set))120{121 int n = read(set_fd, recvbuf, 1024);122 if(n == -1)123 ERR_EXIT("read");124 else if(n == 0)//客户端退出,125 {126FD_CLR(set_fd, &rset);127close(set_fd);128fd_set[i] = -1;129arrlen--;130 }131 write(set_fd, recvbuf, strlen(recvbuf));132memset(recvbuf, 0, 1024);133if(--nready < 0)134 break;135}136 }137}138 }

4

1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #include <unistd.h> 5 #include <errno.h> 6 #include <sys/types.h> 7 #include <sys/stat.h> 8 #include <sys/socket.h> 9 #include <arpa/inet.h> 10 #include <signal.h> 11 #include <poll.h> 12 #define MAXLEN 1024 13 14 #define ERR_EXIT(m) \ 15do { \ 16 perror(m);\ 17 exit(EXIT_FAILURE);\ 18}while(0) 19 20 static void do_service(int); 21 int listenf(); 22 void handle(int signum) 23 { 24printf("hello\n"); 25 } 26 static void do_poll(int); 27 28 int main(int argc, const char *argv[]) 29 { 30if(signal(SIGPIPE, handle) == SIG_ERR) 31 ERR_EXIT("signal"); 32int listenfd = listenf(); 33do_poll(listenfd); 34close(listenfd); 35return 0; 36 } 37 38 int listenf() 39 { 40int listenfd = socket(AF_INET, SOCK_STREAM, 0);//准备一个socketfd 41if(listenfd == -1 ) 42 ERR_EXIT("listen"); 43 44int on = 1; 45if(setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1)//setsockopt设置端口复用 46{ 47 close(listenfd); 48 ERR_EXIT("setsockopt"); 49} 50 51struct sockaddr_in seraddr; 52seraddr.sin_family = AF_INET; 53seraddr.sin_port = htons(8888); 54seraddr.sin_addr.s_addr = htonl(INADDR_ANY); 55socklen_t len = sizeof(seraddr); 56if(bind(listenfd, (struct sockaddr*)&seraddr, len) == -1)//监听socket端口, 57{ 58 close(listenfd); 59 ERR_EXIT("bind"); 60} 61 62if(listen(listenfd, 6) == -1) 63{ 64 close(listenfd); 65 ERR_EXIT("listen"); 66} 67return listenfd; 68 } 69 70 void do_poll(int fd) 71 { 72struct pollfd pfd[MAXLEN];//设置的最大连接数,存放结构体信息 73char recvbuf[1024] = {0}; 74int i; 75for(i = 0; i < MAXLEN; ++i) 76 pfd[i].fd = -1; 77 78pfd[0].fd = fd; 79pfd[0].events = POLLIN;//将监听连接的描述符防止数组开头 80 81int nready; 82int maxi = 0; 83while(1) 84{ 85 nready = poll(pfd, maxi+1, -1);//轮询的是有效数组长度,不能少1 86 if(nready == -1) 87 { 88 ERR_EXIT("select"); 89 } 90 91 if(pfd[0].revents & POLLIN)//有客户端请求连接 92 { 93 int clifd = accept(fd, NULL, NULL); 94 if(clifd == -1) 95 ERR_EXIT("accept"); 96 for(i = 1; i < MAXLEN; ++i) 97 { 98 if(pfd[i].fd == -1) 99 {100 pfd[i].fd = clifd;101 pfd[i].events = POLLIN;102 break;103 }104 }105 if(i > maxi)106 maxi = i; 107 --nready;108 }109 110 for(i = 1; i <= maxi; ++i)111 {112 if(pfd[i].fd == -1)113 continue;114 115 if( pfd[i].revents & POLLIN)116 {117 int n = read(pfd[i].fd, recvbuf, 1024);118 if(n == -1)119 ERR_EXIT("read");120 else if(n == 0)//客户端退出,则从集合中清除121 {122 printf("%d close\n", pfd[i].fd);123 close(pfd[i].fd); 124 pfd[i].fd = -1;125 continue;126 }127 write(pfd[i].fd, recvbuf, strlen(recvbuf));128 memset(recvbuf, 0, 1024);129 130 if(--nready < 0)131 break;132 }133 }134}135 }

5.epoll服务器模型:

1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #include <unistd.h> 5 #include <errno.h> 6 #include <sys/types.h> 7 #include <sys/stat.h> 8 #include <sys/socket.h> 9 #include <arpa/inet.h> 10 #include <signal.h> 11 #include <sys/epoll.h> 12 #define MAXLEN 1024 13 14 #define ERR_EXIT(m) \ 15do { \ 16 perror(m);\ 17 exit(EXIT_FAILURE);\ 18}while(0) 19 20 int listenf(); 21 static void do_epoll(int); 22 23 int main(int argc, const char *argv[]) 24 { 25int listenfd = listenf(); 26do_epoll(listenfd); 27close(listenfd); 28return 0; 29 } 30 31 int listenf() 32 { 33int listenfd = socket(AF_INET, SOCK_STREAM, 0);//准备一个socketfd 34if(listenfd == -1 ) 35 ERR_EXIT("listen"); 36 37int on = 1; 38if(setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1)//setsockopt设置端口复用 39{ 40 close(listenfd); 41 ERR_EXIT("setsockopt"); 42} 43 44struct sockaddr_in seraddr; 45seraddr.sin_family = AF_INET; 46seraddr.sin_port = htons(8888); 47seraddr.sin_addr.s_addr = htonl(INADDR_ANY); 48socklen_t len = sizeof(seraddr); 49if(bind(listenfd, (struct sockaddr*)&seraddr, len) == -1)//监听socket端口, 50{ 51 close(listenfd); 52 ERR_EXIT("bind"); 53} 54 55if(listen(listenfd, 6) == -1) 56{ 57 close(listenfd); 58 ERR_EXIT("listen"); 59} 60return listenfd; 61 } 62 63 void do_epoll(int fd) 64 { 65char recvbuf[MAXLEN] = {0}; 66int epollfd = epoll_create(2048);//设置的最大连接数 67if(epollfd == -1) 68 ERR_EXIT("epoll_create"); 69 70struct epoll_event ev; 71ev.data.fd = fd; 72ev.events = EPOLLIN; 73if(epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &ev) == -1)//加入轮询 74 ERR_EXIT("epoll_ctl_add"); 75 76struct epoll_event events[2048];//数组在epoll_wait返回结果的时候使用 77int ret; 78int i;//在下面while的for循环中遍历使用 79int rfd; 80int clientfd; 81int nread; 82while(1) 83{ 84 ret = epoll_wait(epollfd, events, 2048, -1); 85 if(ret == -1) 86 ERR_EXIT("epoll_wait"); 87 88 for(i = 0; i < ret; ++i ) 89 { 90 rfd = events[i].data.fd; 91 if(rfd == fd) 92 { 93 if((clientfd = accept(fd, NULL, NULL)) == -1) 94 ERR_EXIT("accept"); 95 ev.data.fd = clientfd; 96 ev.events = EPOLLIN; 97 if(epoll_ctl(epollfd, EPOLL_CTL_ADD, clientfd, &ev) == -1) 98 ERR_EXIT("epoll_ctl"); 99 }else100 {101 int nread = read(rfd, recvbuf, MAXLEN);102 if(nread == -1)103 {104 if(errno == EINTR)105continue;106 ERR_EXIT("read");107 }else if( nread == 0)//客户端退出,从epoll轮询中删除108 {109 printf("%d fd close\n", rfd);110 ev.data.fd = rfd;111 ev.events = EPOLLIN;112 if(epoll_ctl(epollfd, EPOLL_CTL_DEL, rfd, &ev) == -1)113ERR_EXIT("epoll_ctl");114 }else115 {116 if(write(rfd, recvbuf, strlen(recvbuf)) == -1)117ERR_EXIT("write");118 memset(recvbuf, 0, MAXLEN);119 }120 }121 }122}123close(epollfd);124 }

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