美文网首页
Linux--select

Linux--select

作者: 锈色的栅栏 | 来源:发表于2024-11-03 09:03 被阅读0次

    select函数概述

    select允许程序可以监视多个文件描述符(套接字)的(可读,可写,异常),直到一个或多个文件描述符(套接字)准备就绪(超时),select解阻塞继续执行。

    #include <sys/select.h>
    #include <sys/time.h>
    #include <sys/types.h>
    #include <unistd.h>

    int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);

    select参数介绍

    nfds: 是这三个集合中编号最高的文件描述符是加1。
    readfds:监视readfds集合中的描述符是否读操作准备就绪。
    writefds:监视writefds集合中的描述符是否写操作准备就绪
    exceptfds:监视exceptfds集合中的描述符是否发生了异常。
    timeout:超时时间,如果在超时时间内没有任意描述符准备好或异常,那么select超时时间一到也会解阻塞

    struct timeval
    {
        long tv_ sec; /* seconds */
        long tv_ usec; /* microseconds */
    };

    timeout有三种情况:
    timeout为NULL 表示永远等待下去
    timeout中所有成员问0, 不等待立即解阻塞
    timeout中成员有固定的时间 表示等待该时间

    返回值:
            > 0:表示就绪的文件描述符数量。
            =0:表示超时。
            -1:表示select出错。

    描述符集合操作API

    集合类型
           fd_set
    清空集合
            void FD_ ZERO( fd_ set *fdset);
    将fd描述符 添加到集合中
            void FD_ SET( int fd, fd_ set *fdset);
    将fd描述符 从集合中删除
            void FD_CLR( int fd, fd_ set *fdset);
    判断fd描述符 是否在集合中
            int FD_ ISSET( int fd, fd_ set *fdset);

    示例代码

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <pthread.h>
    #include <sys/socket.h>//socket
    #include <netinet/in.h> //struct sockaddr_in
    #include <strings.h>
    #include <sys/select.h>
    #include <arpa/inet.h>

    int create_tcp_socket(unsigned short port);
    void sys_err(const char *err);

    int main(int argc,char *argv[]) {   
            int lfd = create_tcp_socket(9999);       
            fd_set old_set,r_set;   
            FD_ZERO(&old_set);   
            FD_SET(lfd,&old_set);//将lfd添加到old_set中   
            int maxfd = lfd;   
            while (1)//select 需要循环监听文件描述符的状态   
            {       
                    fd_set r_set = old_set;       
                    int nready = select(maxfd+1,&r_set,NULL,NULL,NULL);       
                    if(nready < 0){           
                            sys_err("select");       
                    }else if(nready > 0){           
                            if(FD_ISSET(lfd,&r_set)){               
                                    //printf("connect\n");               
                                    struct sockaddr_in cil_addr;               
                                    socklen_t cli_len = sizeof(cil_addr); 
                                    int cfd = accept(lfd,(struct sockaddr *)&cil_addr,&cli_len); 
                                   printf("connect %s : %hu\n",                                                inet_ntoa(cil_addr.sin_addr),ntohs(cil_addr.sin_port));
                                    if(cfd > maxfd)                   
                                                maxfd = cfd;               
                                    FD_SET(cfd,&old_set);               
                                    if(--nready == 0)
                                                continue;           
                                }           
                                 int i = 0;
                                 for (i = lfd+1; i <= maxfd; i++)
                                {               
                                            if(FD_ISSET(i,&r_set)){
                                                    unsigned char buf[1500] = "";
                                                    int n = recv(i,buf,sizeof(buf),0);
                                                    if(n < 0){ 
                                                               perror("recv");
                                                    }else if (n == 0)
                                                    { 
                                                               FD_CLR(i,&old_set);
                                                                close(i); 
                                                                   printf("退出了\n");
                                                     }else if (n > 0)
                                                     { 
                                                               send(i,buf,n,0);
                                                     }
                                            }
                                 }
                   }   
            }   
         close(lfd);   
         return 0;
    }

    int create_tcp_socket(unsigned short port){   
            int lfd = socket(AF_INET,SOCK_STREAM,0);   
            if(lfd < 0)       
                    sys_err("socket error");       
            int opt = 1;   
            setsockopt(lfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));   
            struct sockaddr_in my_addr;   
            bzero(&my_addr,sizeof(my_addr));   
            my_addr.sin_family = AF_INET;   
            my_addr.sin_port = htons(port);   
            my_addr.sin_addr.s_addr = htonl(INADDR_ANY);   
            int ret = bind(lfd,(struct sockaddr *)&my_addr,sizeof(my_addr));   
            if(ret < 0)       
                    sys_err("bind error");   
            listen(lfd,128);   
            return lfd;
    }

    void sys_err(const char *err){   
             perror(err);   
            _exit(-1);  
    }

    相关文章

      网友评论

          本文标题:Linux--select

          本文链接:https://www.haomeiwen.com/subject/zthidjtx.html