I/O 多路转接 select

读一个文件描述符写另一个文件描述符时迫切需要

int select (int maxfdp1,fd_set *restrict readfds,fd_set * restrict writefds,fd_set * restrict exceptfds,struct timeval * restrict tvptr);

readfds,writefds,execptfds 是我们关心的可读可写 和异常的文件描述符集合

maxfdp1 表示最大文件描述符号+1的数

tvptr==null  永远等待

tvptr->tv_sec==0&&tvptr->usec==0  不等待  直接检测

文件描述符集合需要用一下几个函数:

int FD_ISSET(int fd,fd_set *fdset);         //检测是否是 打开状态 select 函数返回时候

void FD_CLR(int fd,fd_set *fdset);    //将某一位关闭

void FD_SET(int fd,fd_set *fdset);    //将某一位开启

void FD_ZERO(fd_set * fdset);    //将一个fsd_set 变量所有位设置为0  初始化时候使用

需要注意的是 每次调用select函数的之前 都需要 初始化和设置fd_set

void relay(int fd1,int fd2)
{
    struct fsm_st fsm12,fsm21;
    int fd1_save,fd2_save;
    fd_set rset,wset;    

    fd1_save = fcntl(fd1,F_GETFL);//获取文件描述符状态
    fcntl(fd1,F_SETFL,fd1_save|O_NONBLOCK);//加上为阻塞状态
    fd2_save = fcntl(fd2,F_GETFL);
        fcntl(fd2,F_SETFL,fd2_save|O_NONBLOCK);

    fsm12.state = STATE_R;
    fsm12.sfd = fd1;
    fsm12.dfd = fd2;

    fsm21.state = STATE_R;
    fsm21.sfd = fd2;
    fsm21.dfd = fd1;

    while(fsm12.state != STATE_T || fsm21.state != STATE_T)
    {
        /*布置监视任务*/

        FD_ZERO(&rset);
        FD_ZERO(&wset);
        
        if(fsm12.state == STATE_R)
            FD_SET(fsm12.sfd,&rset);
        if(fsm12.state == STATE_W)
            FD_SET(fsm12.dfd,&wset);
        if(fsm21.state == STATE_R)
            FD_SET(fsm21.sfd,&rset);
        if(fsm21.state == STATE_W)
            FD_SET(fsm21.dfd,&wset);


        /*监视*/
        if(fsm12.state < STATE_AUTO || fsm21.state < STATE_AUTO)
        {
            if(select(max(fd1,fd2)+1,&rset,&wset,NULL,NULL) < 0)
            {
                if(errno == EINTR)
                    continue;
                perror("select()");
                exit(1);
            }
        }
        /*查看监视结果*/
        if(FD_ISSET(fd1,&rset) || FD_ISSET(fd2,&wset) || fsm12.state > STATE_AUTO)
            fsm_driver(&fsm12);
        if(FD_ISSET(fd2,&rset) || FD_ISSET(fd1,&wset) || fsm21.state > STATE_AUTO)
            fsm_driver(&fsm21);
    }

    fcntl(fd1,F_SETFL,fd1_save);//还原文件描述符状态
    fcntl(fd2,F_SETFL,fd2_save);
    
}
原文地址:https://www.cnblogs.com/qingducx/p/5205936.html