多路复用的server模型

多路复用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 }

你可能感兴趣的:(server)