zoukankan      html  css  js  c++  java
  • 第十七篇:IO复用之select实现

    前言

           在看过前文:初探IO复用后,想必你已对IO复用这个概念有了初步但清晰的认识。

           接下来,我要在一个具体的并发客户端中实现它(基于select函数),使得一旦服务器中的客户进程被终止的时候,客户端这边立即得到通知并返回异常。

    select函数

    函数原型:int select ( int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, const struct timeval *timeout )

    包含头文件:sys/select.h  sys/time.h ( 两个都要包含 )

    参数说明:maxfdp1表示监听描述符个数( 一般直接赋予最大描述符号的值+1 ),中间几个参数表示具体的监听描述符集( 读/写/异常描述符集,本质是位向量组 ),最后一个参数表示监听的时间限制结构体。

    配套使用宏:

    1. void FD_ZERO ( fd_set *fdset ) 监听描述符集清零

    2. void FD_SET ( int fd, fd_set *fset ) 注册要监听的描述符

    3. void FD_CLR ( int fd, fd_set *fdset ) 注销不要监听的描述符

    4. int FD_ISSET ( int fd, fd_set *fdset ) 判断某个监听信号是否接收到( 一般用于在select函数调用后某个信号是否接收到判断 )

    返回值:返回已经就绪的描述符的个数,如果是定时器到时则返回0,出错则返回-1。

    大致用法:

    1. 定义一个空的描述符集

    以下部分循环:

    2. 注册要监听的描述符

    3. 调用select函数

    4. 依次编写IO处理代码( 一般是if ( FD_ISSET(描述符), &监听描述符集 ) { } 这样的结构 )。

    代码实现

           下面的代码对之前的客户端代码做了修改,增加了基于select函数的IO复用机制:

     1 #include    "unp.h"
     2 
     3 void
     4 str_cli(FILE *fp, int sockfd)
     5 {
     6     int            maxfdp1;
     7     // 定义描述符集
     8     fd_set        rset;
     9     char        sendline[MAXLINE], recvline[MAXLINE];
    10 
    11     // 清空描述符集
    12     FD_ZERO(&rset);
    13     for ( ; ; ) {
    14         // 注册要监听的两个描述符
    15         FD_SET(fileno(fp), &rset);
    16         FD_SET(sockfd, &rset);
    17         // 计算最大描述符并将它+1后作为select函数的第一个参数
    18         maxfdp1 = max(fileno(fp), sockfd) + 1;
    19         // 调用并阻塞于select函数
    20         Select(maxfdp1, &rset, NULL, NULL, NULL);
    21 
    22         // 读取回射以及处理TCP分节
    23         if (FD_ISSET(sockfd, &rset)) {    
    24             if (Readline(sockfd, recvline, MAXLINE) == 0)
    25                 err_quit("str_cli: server terminated prematurely");
    26             Fputs(recvline, stdout);
    27         }
    28 
    29         // 处理用户输入
    30         if (FD_ISSET(fileno(fp), &rset)) { 
    31             if (Fgets(sendline, MAXLINE, fp) == NULL)
    32                 return;        
    33             Writen(sockfd, sendline, strlen(sendline));
    34         }
    35     }
    36 }

    运行测试

           经过测试,发现当服务器杀死客户端子进程后,客户端这边立刻报错并退出了程序。

  • 相关阅读:
    Redis数据库
    python的web运用
    python对 if __name__=='__main__'的理解
    python的函数
    python的四种内置数据结构
    python的循环和选择
    关于oracle设置主键自增的问题
    用HttpClient和用HttpURLConnection做爬虫发现爬取的代码少了的问题
    ORACLE not available如何解决
    集合(下)
  • 原文地址:https://www.cnblogs.com/muchen/p/6877664.html
Copyright © 2011-2022 走看看