并发服务器模型:IO复用循环服务器
2011-07-15 11:24
381 查看
1、简介
前面的服务器模型主要集中在并发服务器上,并发服务器有个比较大的缺陷,它需要建立多个并行的处理单元。当客户端增加时,随着处理单元的增加,系统的负载会逐渐转移到并行单元的现场切换上。因此有一个比较新型的IO复用循环服务器。该模型在系统开始时,建立多个不同工作类型的处理单元,当客户端的请求到来时,将客户端的连接放到一个状态池中,对所有客户端的连接状态在一个处理单元中进行轮询处理。
2、tcp模型
3、服务器源代码(concurrency-server5.c):
4、客户端源代码(concurrency-client.c)与之前的一样。
5、编译源代码:
new@new-desktop:~/linux/c$ gcc -Wall –lpthread concurrency-server5.c -o server
new@new-desktop:~/linux/c$ gcc -Wall concurrency-client.c -o client
6、运行,试试吧
前面的服务器模型主要集中在并发服务器上,并发服务器有个比较大的缺陷,它需要建立多个并行的处理单元。当客户端增加时,随着处理单元的增加,系统的负载会逐渐转移到并行单元的现场切换上。因此有一个比较新型的IO复用循环服务器。该模型在系统开始时,建立多个不同工作类型的处理单元,当客户端的请求到来时,将客户端的连接放到一个状态池中,对所有客户端的连接状态在一个处理单元中进行轮询处理。
2、tcp模型
3、服务器源代码(concurrency-server5.c):
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <sys/socket.h> #include <arpa/inet.h> #include <netinet/in.h> #include <sys/types.h> #include <unistd.h> #include <time.h> #include <pthread.h> #define BUFLEN 1024 #define THREADNUM 2 #define CLIENTNUM 1024 int connect_host[CLIENTNUM]; int connect_num = 0; /*******************并发服务器模型之五:IO复用循环服务器**********************/ static void *handle_request(void *argv){ char buf[BUFLEN]; int len; time_t now; int maxfd = -1; fd_set rfds; struct timeval tv; tv.tv_sec = 1; tv.tv_usec = 0; int i =0; int err = -1; while(1){ FD_ZERO(&rfds); for(i = 0; i < CLIENTNUM; i++){ if(connect_host[i] != -1){ FD_SET(connect_host[i],&rfds); if(maxfd < connect_host[i]) maxfd = connect_host[i]; } } err = select(maxfd+1, &rfds, NULL, NULL, &tv); switch(err){ case 0: break; case -1: break; default: if (connect_num < 0) break; for(i = 0; i < CLIENTNUM; i++){ if(connect_host[i] != -1){ if(FD_ISSET(connect_host[i],&rfds)){ /******处理客户端请求*******/ bzero(buf,BUFLEN); len = recv(connect_host[i],buf,BUFLEN,0); if(len >0 && !strncmp(buf,"TIME",4)){ bzero(buf,BUFLEN); /*获取系统当前时间*/ now = time(NULL); /*ctime将系统时间转换为字符串,sprintf使转化后的字符串保存在buf*/ sprintf(buf,"%24s\r\n",ctime(&now)); //******发送系统时间*******/ send(connect_host[i],buf,strlen(buf),0); } /*关闭通讯的套接字*/ close(connect_host[i]); /*更新文件描述符在数组中的值*/ connect_host[i] = -1; connect_num--; } } } break; } } return NULL; } static void *handle_connect(void *arg){ int sockfd = *((int *)arg); int newfd; struct sockaddr_in c_addr; socklen_t len; int i; while(1){ len = sizeof(struct sockaddr); if((newfd = accept(sockfd,(struct sockaddr*) &c_addr, &len)) >0){ printf("\n*****************通信开始***************\n"); printf("正在与您通信的客户端是:%s: %d\n",inet_ntoa(c_addr.sin_addr),ntohs(c_addr.sin_port)); for(i = 0; i < CLIENTNUM; i++){ if(connect_host[i] == -1){ connect_host[i] = newfd; /*客户端计数器*/ connect_num++; /*继续等待新的客户端*/ break; } } } } return NULL; } int main(int argc, char **argv) { int sockfd; struct sockaddr_in s_addr; unsigned int port, listnum; pthread_t thread_s[2]; /**/ memset(connect_host,-1,CLIENTNUM); /*建立socket*/ if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1){ perror("socket"); exit(errno); }else printf("socket create success!\n"); /*设置服务器端口*/ if(argv[2]) port = atoi(argv[2]); else port = 4567; /*设置侦听队列长度*/ if(argv[3]) listnum = atoi(argv[3]); else listnum = 3; /*设置服务器ip*/ bzero(&s_addr, sizeof(s_addr)); s_addr.sin_family = AF_INET; s_addr.sin_port = htons(port); if(argv[1]) s_addr.sin_addr.s_addr = inet_addr(argv[1]); else s_addr.sin_addr.s_addr = INADDR_ANY; /*把地址和端口帮定到套接字上*/ if((bind(sockfd, (struct sockaddr*) &s_addr,sizeof(struct sockaddr))) == -1){ perror("bind"); exit(errno); }else printf("bind success!\n"); /*侦听本地端口*/ if(listen(sockfd,listnum) == -1){ perror("listen"); exit(errno); }else printf("the server is listening!\n"); /*创建线程处理客户端的连接*/ pthread_create(&thread_s[0],NULL,handle_connect,(void *)&sockfd); /*创建线程处理客户端的请求*/ pthread_create(&thread_s[1],NULL,handle_request, NULL); /*等待线程结束*/ int i; for(i = 0; i < THREADNUM; i++){ pthread_join(thread_s[i],NULL); } /*关闭服务器的套接字*/ close(sockfd); return 0; }
4、客户端源代码(concurrency-client.c)与之前的一样。
5、编译源代码:
new@new-desktop:~/linux/c$ gcc -Wall –lpthread concurrency-server5.c -o server
new@new-desktop:~/linux/c$ gcc -Wall concurrency-client.c -o client
6、运行,试试吧
相关文章推荐
- Linux网络编程服务器模型选择之IO复用循环并发服务器
- 服务器编程模型 循环服务器->IO复用循环服务器 并发服务器->高性能并发服务器
- Linux网络编程服务器模型选择之IO复用循环并发服务器
- 唯快不破:高性能网络服务器5--IO复用与并发模型
- 高性能网络服务器5--IO复用与并发模型
- IO复用(Reactor模式和Preactor模式)——用epoll来提高服务器并发能力
- IO复用、多进程和多线程三种并发编程模型
- IO复用、多进程和多线程三种并发编程模型
- 一只简单的网络爬虫(基于linux C/C++)————浅谈并发(IO复用)模型
- IO多路复用服务器模型
- IO复用、多进程和多线程三种并发编程模型比较
- C/S通信---服务器IO多路复用模型之poll的使用
- 12 IO复用服务器模型
- 高并发服务器设计之多路复用模型
- C/S通信---服务器IO多路复用模型之select的使用
- IO复用、多进程和多线程三种并发编程模型
- C/S通信---服务器IO多路复用模型之epoll的使用
- 服务器IO多路复用模型
- 循环服务器,并发服务器模型以及I/O多路转接模型
- IO模型与TCP并发服务器