zoukankan      html  css  js  c++  java
  • linux—select具体解释

    linux—select具体解释

     

    select系统调用时用来让我们的程序监视多个文件句柄的状态变化的。程序会停在select这里等待,直到被监视的文件句柄有一个或多个发生了状态改变。

    关于文件句柄,事实上就是一个整数,通过socket函数的声明就明确了:

    int socket(int domain, int type, int protocol);

    我们最熟悉的句柄是012三个,0是标准输入,1是标准输出,2是标准错误输出。012是整数表示的,相应的FILE *结构的表示就是stdinstdoutstderr

    继续上面的select,就是用来监视某个或某些句柄的状态变化的。select函数原型例如以下:

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

    函数的最后一个參数timeout是一个超时时间值。其类型是struct timeval *,即一个struct timeval结构的变量的指针,所以我们在程序里要声明一个struct timeval tv;然后把变量tv的地址&tv传递给select函数。struct timeval结构例如以下:

    struct timeval

    {

           long tv_sec;  //seconds

           long tv_usec; //microseconds

    }

    234三个參数是一样的类型;fd_set *,即我们在程序里要申请几个fd_set类型的变量,比方rdfdswtfdsexfds,然后把这个变量的地址&rdfds,&wtfds,&exfds传递给select函数。这三个參数都是一个句柄的集合,第一个rdfds是用来保存这种句柄的:当句柄的状态变成可读时系统就告诉select函数返回,同理第二个函数是指向有句柄状态变成可写时系统就会告诉select函数返回,同理第三个參数exfds是特殊情况,即句柄上有特殊情况发生时系统会告诉select函数返回。特殊情况比方对方通过一个socket句柄发来了紧急数据。假设我们程序里仅仅想检測某个socket是否有数据可读,我们能够这样:

    fd_set  rdfds;

    struct timeval tv;

    int ret;

    FD_ZERO(&rdfds);

    FD_SET(socket, &rdfds);

    tv.tv_sec = 1;

    tv.tv_uses = 500;

    ret = select (socket + 1, %rdfds, NULL, NULL, &tv);

    if(ret < 0) perror (“select”);

    else if (ret = = 0) printf(“time out”);

    else {

           printf(“ret = %d/n”,ret);

           if(FD_ISSET(socket, &rdfds)){

        /* 读取socket句柄里的数据 */

    recv( );

    }

    }

    注意select函数的第一个參数,是全部增加集合的句柄值的最大那个那个值还要加1.比方我们创建了3个句柄;

    int sa, sb, sc;

    sa = socket(……);

    connect (sa,….);

     

    sb = socket(….);

    connect (sb,…);

     

    sc = socket(….);

    connect(sc,…);

     

    FD_SET(sa, &rdfds);

    FD_SET(sb, &rdfds);

    FD_SET(sc, &rdfds);

     

    在使用select函数之前,一定要找到3个句柄中的最大值是哪个,我们一般定义一个变量来保存最大值,取得最大socket值例如以下:

    int maxfd = 0;

    if(sa > maxfd) maxfd = sa;

    if(sb > maxfd) maxfd = sb;

    if(sc > maxfd) maxfd = sc;

     

    然后调用select函数:

    ret = select (maxfd+1, &rdfds, NULL, NULL,&tv);

     

    相同的道理,假设我们是检測用户是否按了键盘进行输入,我们就应该把标准输入0这个句柄放到select里来检測,例如以下:

    FD_ZERO(&rdfds);

    FD_SET(0, &rdfds);

    tv.tv_sec = 1;

    tv.tv_usec = 0;

    ret = select (1, &rdfds,NULL,NULL,&tv);

    if(ret < 0) perror(“select”);

    else if (ret = = 0) printf (“time out/n”);

    else{

           scanf(“%s”,buf);

    }

  • 相关阅读:
    记某app内购破解 – 安卓逆向菜鸟的初体验
    初探Android逆向:通过游戏APP破解引发的安全思考
    用IKVMC将jar转成dll供c#调用
    Java与.net 关于URL Encode 的区别
    RSA加密、解密、签名、验签的原理及方法
    C#使用SHA1加密类(RSAFromPkcs8)支持1024位和2048位私钥
    java与.net平台之间进行RSA加密验证
    RSA密钥,JAVA与.NET之间转换
    全面解决.Net与Java互通时的RSA加解密问题,使用PEM格式的密钥文件
    Android中Activity的启动模式(LaunchMode)和使用场景
  • 原文地址:https://www.cnblogs.com/zfyouxi/p/4288259.html
Copyright © 2011-2022 走看看