多路复用的server模型

来源:互联网 发布:windows10自带软件 编辑:程序博客网 时间:2024/05/17 23:18
多路复用I/O之server模型 
 主要是关于select()这个函数: 
其原型是:int select(int n,fd_set *read_fds,fd_set *write_fds,fd_set  


*except,struct timeval *timeout); 


功能是:监测指定集合中指定文件描述符的指定事件是否发生; 
参数一:读集合,监测登记文件描述的读事件; 
参数二:写集合,监测登记文件描述的写事件 
参数三:报错集合,监测登记文件描述的报错事件 


void FD_CLR(int fd, fd_set *set); //从指定集合中把指定文件描述删 


除 
int  FD_ISSET(int fd, fd_set *set); //测试指定集合中的指定文件描述 


的事件 
void FD_SET(int fd, fd_set *set); //向指定集合中添加指定文件描述 
void FD_ZERO(fd_set *set); //初始化集合 




  1 #include <stdio.h> 
  2 #include <sys/time.h> 
  3 #include <sys/types.h> 
  4 #include <unistd.h> 
  5 #include <fcntl.h> 
  6 #include <sys/types.h>          /* See NOTES */ 
  7 #include <sys/socket.h> 
  8 #include <netinet/in.h> 
  9 #include <arpa/inet.h> 
 10  
 11 #include <string.h> 
 12  
 13 #define PORT    6543 
 14  
 15 int main() 
 16 { 
 17         /*创建套接字,用于连接*/ 
 18         int s = socket(AF_INET, SOCK_STREAM, 0); 
 19         if(0 > s){ 
 20                 perror("socket"); 
 21                 return -1; 
 22         } 
 23  
25  
 26         /*端口重用*/ 
 27         int reuseaddr = 1; 
 28         if(0 > setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &reuseaddr,  


sizeof(re    useaddr))){ 
 29                 perror("setsockopt"); 
 30                 return -1; 
 31         } 
 32  
 33  
 34  
 35         /*绑定server IP及端口号*/ 
 36         struct sockaddr_in addr; 
 37         memset(&addr, 0, sizeof(struct sockaddr_in)); 
 38         addr.sin_family = AF_INET; 
 39         addr.sin_port = htons(PORT); 
 40         addr.sin_addr.s_addr = htonl(INADDR_ANY); 
 41  
 42         socklen_t addrlen = sizeof(struct sockaddr_in); 
 43         /*struct sockaddr_in addr初始化必须,socklen_t addrlen*/ 
 44         if(0 > bind(s, (struct sockaddr *)&addr, addrlen)){ 
 45                 perror("bind"); 
 46                 return -1; 
 47         } 
 48  
 49         /*设置监听数*/ 
 50         listen(s, 10); 
 51  
 52         /*设置套接字为非阻塞*/ 
 53         int val = fcntl(s, F_GETFL, 0); 
 54         val |= O_NONBLOCK; 
 55         fcntl(s, F_SETFL, val); 
 56  
 57         /*初始化读集合*/ 
 58         fd_set oldset, newset; 
 59 /////这里将oldset集合初始化 
 60         FD_ZERO(&oldset); 
 61  
 62 ////将开始的套接字添加到集合oldset中 
 63         FD_SET(s, &oldset); 
 64  
 65  
 66 ///这里用maxfd得到最大的套接字数 
 67         int maxfd = s+1; 
 68  
 69 //////这里设置为select功能实现的时间,超过跳过 
 70         struct timeval tm = { 
 71                 .tv_sec = 1, 
 72                 .tv_usec= 0, 
 73         }; 
 74  
 75         printf("Wait for connecting .\n"); 
 76         while(1){ 
 77  
 78 //              printf("-------------1-----------\n");           
 79 ////将oldset这个集合copy给newset(动态包含的套接字的集合) 
 80                 newset = oldset; 
 81                 //int ret = select(maxfd, &newset, NULL, NULL,  


&tm); 
 82  
 83 ////////下面将集合newset,用读监听,而且这里没有设置功能运行时间 
 84                 int ret = select(maxfd, &newset, NULL, NULL, NULL); 
 85                 printf("------------------------\n"); 
86                 if(0 > ret){ 
 87                         perror("select"); 
 88                         return -1; 
 89                 }else if(0 == ret){  //////如果超时运行这个条件 
 90                         printf("Timeout.\n"); 
 91                         continue; 
 92                 }else{ 
 93                         /////select成功 
 94 //              printf("-------------1-----------\n");           
 95                         /*测试用于连接的套接字,看是否有新连接进来 


*/ 
 96                         if(FD_ISSET(s, &newset)){ 
 97                                 struct sockaddr_in newaddr; 
 98                                 memset(&newaddr, 0, sizeof(struct  


sockaddr_i    n)); 
 99                                 socklen_t newlen = sizeof(struct  


sockaddr_in    ); 
100                                 /*有新连接进来,得到用于读写到套接 


字*/ 
101                                 int news = accept(s, (struct  


sockaddr *)&new    addr, &newlen); 
102                                 if(0 > news){ 
103                                         perror("accept"); 
104                                         return -1; 
105                                 } 
106                                 /*把套接字保存进集合*/ 
107                         //      printf("-------------1----------- 


\n");               
108  
109                                 FD_SET(news, &oldset); 
110                                 if(news+1 > maxfd) { 
111                                         maxfd = news+1; 
112                                 } 
113                 //              maxfd++; 
114                                 printf("New connect: SOCKET[%d], % 


s:%d\n", n    ews, inet_ntoa(newaddr.sin_addr), ntohs 


(newaddr.sin_port)); 
115                         } 
116  
117                         for(int i = s+1; i < maxfd; i++){ 
118                                 /*测试用于读写到套接字,看哪个客户 


端发数据进 
    来*/ 
119                                 if(FD_ISSET(i, &newset)){ 
120                                 #define MAX 64 
121                                         char buf[MAX]; 
122                                         bzero(buf, MAX); 
123                                         int num = recv(i, buf, MAX,  


0); 
124                                         if(0 >= num){ 
125                                                 FD_CLR(i, &oldset); 
126                                                 close(i); 
127                                                 printf("SOCKET[%d]  


leave.\n"    , i); 
128                                                 continue; 
129                                         } 
130                                         printf("SOCKET[%d]: %s[%d] 


\n", i, bu    f, num); 
131                                 } //if 
132                         } //for 
133                 } //if 
134         } //while 
135 }
0 0
原创粉丝点击