zoukankan      html  css  js  c++  java
  • fd_set

    注:网络编程 用c写socket

    select()函数主要是建立在fd_set类型的基础上的。fd_set(它比较重要所以先介绍一下)是一组文件描述字(fd)的集合,它用一位来表示一个fd(下面会仔细介绍),对于fd_set类型通过下面四个宏来操作: 

    fd_set set;

    FD_ZERO(&set);      

    FD_SET(fd, &set);   

    FD_CLR(fd, &set);   

    FD_ISSET(fd, &set);        

    过去,一个fd_set通常只能包含<32的fd(文件描述字),因为fd_set其实只用了一个32位矢量来表示fd;现在,UNIX系统通常会 在头文件<sys/select.h>中定义常量FD_SETSIZE,它是数据类型fd_set的描述字数量,其值通常是1024,这样就 能表示<1024的fd。根据fd_set的位矢量实现,我们可以重新理解操作fd_set的四个宏: 

    fd_set set;

    FD_ZERO(&set);     

    FD_SET(0, &set);   

    FD_CLR(4, &set);     

    FD_ISSET(5, &set);   

    ―――――――――――――――――――――――――――――――――――――――

    注意fd的最大值必须<FD_SETSIZE。

    ――――――――――――――――――――――――――――――――――――――― 

    select函数的接口比较简单:

    int select(int nfds, fd_set *readset, fd_set *writeset,

    fd_set* exceptset, struct tim *timeout); 

    功能:

    测试指定的fd可读?可写?有异常条件待处理?     

    参数:

    nfds: 需要检查的文件描述字个数(即检查到fd_set的第几位),数值应该比三组fd_set中所含的最大fd

           值更大,一般设为三组fd_set中所含的最大fd值加1(如在readset,writeset,exceptset中所含最大

           的fd为5,则nfds=6,因为fd是从0开始的)。设这个值是为提高效率,使函数不必检查fd_set的所

          有1024位。

    readset: 用来检查可读性的一组文件描述字。

    writeset: 用来检查可写性的一组文件描述字。

    exceptset:用来检查是否有异常条件出现的文件描述字。(注:错误不包括在异常条件之内)

    timeout:有三种可能:

            1:timeout=NULL(阻塞:直到有一个fd位被置为1函数才返回)

            2:timeout所指向的结构设为非零时间(等待固定时间:有一个fd位被置为1或者时间耗尽,函数

               均返回)

            3. timeout所指向的结构,时间设为0(非阻塞:函数检查完每个fd后立即返回) 

    返回值:     

    返回对应位仍然为1的fd的总数。 

    Remarks:

    三组fd_set均将某些fd位置0,只有那些可读,可写以及有异常条件待处理的fd位仍然为1。

    使用select函数的过程一般是:

    先调用宏FD_ZERO将指定的fd_set清零,然后调用宏FD_SET将需要测试的fd加入fd_set,接着调用函数  

    select测试fd_set中的所有fd,最后用宏FD_ISSET检查某个fd在函数select调用后,相应位是否仍然为1。 

    以下是一个测试单个文件描述字可读性的例子:

    int isready(int fd)

    {

       int rc;

        fd_set fds;

        struct tim tv;    

        FD_ZERO(&fds);

        FD_SET(fd,&fds);

        tv.tv_sec = tv.tv_usec = 0;    

        rc = select(fd+1, &fds, NULL, NULL, &tv);

        if (rc < 0)  //error

           return -1;    

        return FD_ISSET(fd,&fds) ? 1 : 0;

     }

    下面还有一个复杂一些的应用:

    //这段代码将指定测试Socket的描述字的可读可写性,因为Socket使用的也是fd

    uint32 SocketWait(TSocket *s,bool rd,bool wr,uint32 timems)    

    {

        fd_set rfds,wfds;

     #ifdef _WIN32

        TIM tv;

     #else

        struct tim tv;

     #endif    

        FD_ZERO(&rfds);

        FD_ZERO(&wfds); 

        if (rd)   //TRUE

         FD_SET(*s,&rfds);  //添加要测试的描述字 

        if (wr)    //FALSE

          FD_SET(*s,&wfds); 

        tv.tv_sec=timems/1000;    //second

        tv.tv_usec=timems00;    //ms 

        for (;;) //如果errno==EINTR,反复测试缓冲区的可读性

            switch(select((*s)+1,&rfds,&wfds,NULL,

                (timems==TIME_INFINITE?NULL:&tv))) //测试在规定的时间内套接口接收缓冲区中是否有数据可读

            {                                         //0--超时,-1--出错

            case 0:    

                return 0; 

            case (-1):   

                 if (SocketError()==EINTR)

                     break;              

                return 0; //有错但不是EINTR 

            default:

                 if (FD_ISSET(*s,&rfds)) //如果s是fds中的一员返回非0,否则返回0

                     return 1;

                 if (FD_ISSET(*s,&wfds))

                     return 2;

                return 0;

            };

    }

  • 相关阅读:
    Java实现 洛谷 P1060 开心的金明
    (Java实现) 洛谷 P1605 迷宫
    (Java实现) 洛谷 P1605 迷宫
    (Java实现)洛谷 P1093 奖学金
    (Java实现)洛谷 P1093 奖学金
    Java实现 洛谷 P1064 金明的预算方案
    Java实现 洛谷 P1064 金明的预算方案
    (Java实现) 洛谷 P1031 均分纸牌
    QT树莓派交叉编译环开发环境搭建(附多个exe工具下载链接)
    武则天红人对唐睿宗的桃色报复(如此缺少城府,注定了要在宫廷中过早地出局)
  • 原文地址:https://www.cnblogs.com/Christine/p/2383392.html
Copyright © 2011-2022 走看看