• 【网络编程】学习笔记05 I/O多路复用之select


    运行select的server端:

     1 #include<stdio.h>
     2 #include<stdlib.h>
     3 #include<string.h>
     4 #include<unistd.h>
     5 #include<errno.h>
     6 #include<pthread.h>
     7 #include<ctype.h>
     8 #include<sys/socket.h>
     9 #include<arpa/inet.h>
    10 
    11 #define SERV_PORT 9527
    12 
    13 void sys_err(const char *str)
    14 {
    15     perror(str);
    16     exit(1);
    17 }
    18 
    19 int main(int argc,char *argv[])
    20 {
    21     int listenfd = 0,connfd = 0;
    22     char buf[BUFSIZ];
    23 
    24     struct sockaddr_in serv_addr,clie_addr;
    25     socklen_t clie_addr_len;
    26     
    27     listenfd = socket(AF_INET,SOCK_STREAM,0);
    28 
    29     int opt = 1;
    30     setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
    31 
    32     memset(&serv_addr,0,sizeof(serv_addr));
    33     serv_addr.sin_family = AF_INET;
    34     serv_addr.sin_port = htons(SERV_PORT);
    35     serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    36     bind(listenfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr));
    37     listen(listenfd,128);
    38 
    39     fd_set rset,allset;                 //定义读集合rset,备份集合allset
    40     int ret,maxfd = 0,n,i,j;
    41     maxfd = listenfd;                   //最大文件描述符
    42 
    43     FD_ZERO(&allset);                   //清空监听集合
    44     FD_SET(listenfd,&allset);           //将待监听fd添加到监听集合中
    45 
    46     while(1){
    47         rset = allset;                  //备份
    48         ret = select(maxfd+1, &rset, NULL, NULL,NULL);  //使用select监听
    49         
    50         if(FD_ISSET(listenfd,&rset)){               //listenfd满足监听读事件
    51             clie_addr_len = sizeof(clie_addr);
    52             connfd = accept(listenfd, (struct sockaddr *)&clie_addr, &clie_addr_len); //与客户端建立连接,不会阻塞
    53 
    54             FD_SET(connfd, &allset);        //将新产生的fd添加到监听集合中,监听数据读事件
    55             if(maxfd < connfd)              //修改maxfd
    56                 maxfd = connfd;
    57 
    58             if(ret == 1)                    //说明select返回值只有1个,并且是listenfd,后续无需执行
    59                 continue;
    60         }
    61         for(i = listenfd+1; i<=maxfd; i++){     //处理满足读事件的fd
    62             if(FD_ISSET(i,&rset)){              //找到满足读事件的fd
    63                 n = read(i,buf,sizeof(buf));
    64                 if(n == 0){                     //检测到客户端已经关闭连接
    65                     close(i);
    66                     FD_CLR(i,&allset);          //将关闭的fd移除出监听集合
    67                 }
    68 
    69                 for(j = 0; j < n;j++)
    70                     buf[j] = toupper(buf[j]);
    71 
    72                 write(i,buf,n);
    73                 write(STDOUT_FILENO,buf,n);
    74             }
    75         }
    76     }
    77     close(listenfd);
    78     return 0;
    79 }

    select的架构如下:

    缺陷:内部判断只能轮询(比如只有3,5,1024,这样的话你需要遍历到死),要优化的话需要加数组。暨监听上限受文件描述符限制,最大1024

       select最多只能支持1024个客户端,如果要5000个客户端就吃不消,所以需要加进程。

    优点:跨平台:win,linux等。而epoll只支持linux

    前ICPC算法竞赛退役选手|现摸鱼ing
  • 相关阅读:
    Excel入门
    夹缝中求和
    移动撤销
    CSP2020-j2 T4 方格取数
    CSP2020-j2 T3表达式(expr)
    直播 获奖(live)
    优秀的拆分(power)
    P5661 公交换乘
    P1160 队列安排
    P1083 借教室
  • 原文地址:https://www.cnblogs.com/Anonytt/p/15545345.html
Copyright © 2020-2023  润新知