Your Ad Here
首页 | 编程语言 | 网站建设 | 游戏天堂 | 冲浪宝典 | 网络安全 | 操作系统 | 软件时空 | 硬件指南 | 病毒相关 | IT 认证
软讯网络 > 编程语言 > C/C++ > select()用法
【标  题】:select()用法
【关键字】:select
【来  源】:http://www.cublog.cn/u/9551/showart.php?id=96380

select()用法

Your Ad Here
我正在读wrox系例中的Beginning Linux Programming,其中socket编程中,针对select用法所举的例子百思不得其解,特请大家帮忙分析指正。

例子是关于一个服务器程序实现对多个客户同时处理的

server1.c 用fork()实现
server2.c 用select()实现

server1.c 主要代码如下:

    while(1) {
        char ch;

        printf("server waiting\n");

/*  Accept connection.  */

        client_len = sizeof(client_address);
        client_sockfd = accept(server_sockfd,
            (struct sockaddr *)&client_address, &client_len);

/*  Fork to create a process for this client and perform a test to see
    whether we're the parent or the child.  */

        if(fork() == 0) {

/*  If we're the child, we can now read/write to the client on client_sockfd.
    The five second delay is just for this demonstration.  */

            read(client_sockfd, &ch, 1);
            sleep(5);
            ch++;
            write(client_sockfd, &ch, 1);
            close(client_sockfd);
            exit(0);
        }

/*  Otherwise, we must be the parent and our work for this client is finished.  */

        else {
            close(client_sockfd);
        }
    }
server2.c 主要代码如下:

    FD_ZERO(&readfds);
    FD_SET(server_sockfd, &readfds);

/*  Now wait for clients and requests.
    Since we have passed a null pointer as the timeout parameter, no timeout will occur.
    The program will exit and report an error if select returns a value of less than 1.  */

    while(1) {
        char ch;
        int fd;
        int nread;

        testfds = readfds;

        printf("server waiting\n");
        result = select(FD_SETSIZE, &testfds, (fd_set *)0,
            (fd_set *)0, (struct timeval *) 0);

        if(result < 1) {
            perror("server5");
            exit(1);
        }

/*  Once we know we've got activity,
    we find which descriptor it's on by checking each in turn using FD_ISSET.  */

        for(fd = 0; fd < FD_SETSIZE; fd++) {
            if(FD_ISSET(fd,&testfds)) {

/*  If the activity is on server_sockfd, it must be a request for a new connection
    and we add the associated client_sockfd to the descriptor set.  */

                if(fd == server_sockfd) {
                    client_len = sizeof(client_address);
                    client_sockfd = accept(server_sockfd,
                        (struct sockaddr *)&client_address, &client_len);
                    FD_SET(client_sockfd, &readfds);
                    printf("adding client on fd %d\n", client_sockfd);
                }

/*  If it isn't the server, it must be client activity.
    If close is received, the client has gone away and we remove it from the descriptor set.
    Otherwise, we 'serve' the client as in the previous examples.  */

                else {
                    ioctl(fd, FIONREAD, &nread);

                    if(nread == 0) {
                        close(fd);
                        FD_CLR(fd, &readfds);
                        printf("removing client on fd %d\n", fd);
                    }

                    else {
                        read(fd, &ch, 1);
                        sleep(5);
                        printf("serving client on fd %d\n", fd);
                        ch++;
                        write(fd, &ch, 1);
                    }
                }
            }
        }
    }
文章的意思是,server2.c 既能借助select()实现server1.c 的及时处理多客户的请求,又避免了server1.c 中有fork()的资源浪费,
问题是:
  
    我看不出server2.c 中的代码实现有任何能 及时处理 多客户请求的地方。
和以下最简单的代码效率是相同的

    listen(server_sockfd, 5);
    while(1) {
        char ch;

        printf("server waiting\n");

/*  Accept a connection.  */

        client_len = sizeof(client_address);
        client_sockfd = accept(server_sockfd,
            (struct sockaddr *)&client_address, &client_len);

/*  We can now read/write to client on client_sockfd.  */

        read(client_sockfd, &ch, 1);
        ch++;
        write(client_sockfd, &ch, 1);
        close(client_sockfd);
    }
大家分析一下,select()的作用到底在哪里?
还有select()一般都用在何处场合?


****************************************
select 用于等待文件描述符变成非阻塞状态(可读、可写、有异常)

第一个参数是文件描述符的最大数目+1   如你的文件描述符是 1 5 15 ,那么就是写16了

第二、三、四参数是要等待的描述符数组
分别表示当可读时、可写时、有异常时

如果你关心某一描述符数组的某一状态,就把它写到对应参数中去
不关心就写NULL

5等待时间。

返回:-1出错0 超时
>;0 满足条件的描述符数目


更多可以自己看代码
或是使用GOOGLE查找

*************************************
select是针对描述符(注意是描述符,包括socket描述符、文件描述符等unix维护的描述福)而言的,主要的作用是用来做多路复用,类似的函数如poll也能实现该功能。当应用程序需要对多种描述符的状态做处理的时候,可以考虑使用select实现,例如应用需要同时处理来自STDIN_FILENO和多个不同socket_read的描述符可读状态,这时候便可以用select来实现多路复用,select函数的具体参数含义和返回值无双斑竹做了详细的描述,其他的人描述了select能够处理的主要三种类型,可读、可写和异常。(另外select可实现较为精确的定时器,可通过设置监测描述符参数为NULL来实现)。大多数得unix系统提供了专门的函数配合select来实现复用,这些函数是FD_CLR(fd, &fdset)、 FD_ISSET(fd, &fdset)、FD_SET(fd, &fdset)、FD_ZERO(&fdset),fd是一个描述符,一般用int来实现兼容性(注意在做STD类型的文件描述符的时候,可以通过fileno转化),fdset是fd_set类型,fd_set是为select设计的数据类型,实际上函数FD_ISSET是通过fd_set的每个bit(注意是比特)变化来监测某一被set的描述符状态变化。
需要说明的一点是该函数不是原子调用,在select阻塞的过程中(如何阻塞通过类型为struct timeval得参数来设置的),需要应用来处理系统发生的任何异常,否则你会发现select可能并没有按照你的意愿去做。
求100内的素数:【上一篇】
sizeof的概念使用方法:【下一篇】
【相关文章】
  • dataTable +selectOneRadio
  • dataTable中selectOneRadio传递多参数
  • dataTable和selectBooleanCheckbox实现选择多条记录
  • Just SQL Part II – The Simple SELECT
  • 如何有效地使用函数select()
  • onselect and onselectstart
  • 谈select列表框
  • winsock i/o的select模型的学习测试
  • 如何解决ACCESS中SELECT TOP语句竟然返回多条记录的问题?
  • 如何解决ACCESS中SELECT TOP语句竟然返回多条记录的问题?
  • 【随机文章】
  • SQL-92定义的术语
  • Sql Server 数据库,想用OLE db连数据库,怎么连呀?
  • 超宽带无线技术“UWB”
  • Oracle 10g SQL 优化再学习
  • 解决make xconfig出现的QT没安装问题。
  • 网游进入“大跃进”时代质疑
  • 奇趣科技CTO来华推介首个开发型linux手机
  • 解决网页下载速度慢的另一种方式
  • 倾听来自观察者模式中两个成员的经典对话。。。
  • BUFFALO BUG:不支持方法重载
  • 【相关评论】
    没有相关评论
    【发表评论】
    姓名:
    邮件:
    随机码*
    评论*
          
    |  首 页  |  版权声明  |  联系我们   |  网站地图  |
    CopyRight © 2004-2007 bbb软讯网络 All Rigths Reserved.