当前位置:首页 > CN2资讯 > 正文内容

并发服务器模型:IO复用循环服务器

3天前CN2资讯

1、简介

前面的服务器模型主要集中在并发服务器上,并发服务器有个比较大的缺陷,它需要建立多个并行的处理单元。当客户端增加时,随着处理单元的增加,系统的负载会逐渐转移到并行单元的现场切换上。因此有一个比较新型的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、运行,试试吧

      你可能想看:

      扫描二维码推送至手机访问。

      版权声明:本文由皇冠云发布,如需转载请注明出处。

      本文链接:https://www.idchg.com/info/23393.html

      分享给朋友:

      “并发服务器模型:IO复用循环服务器” 的相关文章

      Windows中类似rcopy的软件推荐:提升文件复制效率的必备工具

      Windows文件复制的挑战 在Windows操作系统中,文件复制是一个日常操作,但默认的文件复制功能往往无法满足高效、稳定的需求。尤其是在处理大文件或大量文件时,系统自带的复制工具可能会遇到速度慢、容易中断、缺乏错误处理等问题。这些问题不仅影响工作效率,还可能导致数据丢失或损坏。对于需要频繁进行文...

      RackNerd VPS服务测评:性价比高、稳定性强的主机商推荐

      在当今的网络世界中,选择合适的主机商显得尤为重要。我最近体验了RackNerd这家提供VPS服务的主机商,想和大家分享一些我的观点。RackNerd因其性价比高而广受好评,这让我在决定购买前进行了详细的测评。我会从多个角度来探讨RackNerd的各方面表现。 RackNerd不仅在价格上拥有明显优势...

      UCloud年付100元的云服务选择与优势解析

      在开始探讨UCloud的计费方式之前,我想先分享一下我对云服务费用的一些理解和看法。在如今的数字化时代,选择合适的云服务提供商至关重要,计费方式也应兼顾灵活性和经济性。我在UCloud上体验过不同的计费方式,从中得出了一些实用的建议。 UCloud提供的计费方式相当多样,特别是在按年计费这一块。对于...

      VPS去程测试:提升网络性能的关键策略与工具

      在当今数字化时代,VPS(虚拟专用服务器)为各类用户提供了极大的灵活性和控制力。为了确保这种服务能够表现出色,VPS去程测试成为了一个重要的话题。简单来说,去程测试是指从我本地设备到VPS服务器的数据传输路径的检查。这种测试能够帮助我了解数据包在传输过程中的表现,包括延迟和可能的瓶颈。 去程测试的重...

      搬瓦工the plan限量版套餐详解:高性能与性价比的完美结合

      搬瓦工the plan限量版套餐概述 当我第一次听说搬瓦工的“the plan”限量版套餐时,心里忍不住很好奇。这种套餐究竟有什么特别之处?在我深入了解后,发现它不仅仅是一个普通的套餐,而是经过精心设计,专为追求高性能和稳定性的用户打造的。它的背景源于搬瓦工希望为用户提供更优质的服务,满足日益增长的...

      中转机:提升航班灵活性与旅行体验的最佳选择

      中转机的基本定义 中转机,是在航空运输中大量使用的一种方式。简单来说,就是乘客在一段航程中需要在特定的中转站停留,然后再继续前往他们的最终目的地。这个过程中,乘客的航空器可能会更换,或者在中转站转机的时间不同。中转机的作用主要体现在提高航班的灵活性与覆盖范围上。 我想起了自己那次在国外旅行时的经历。...