• 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 }

    运行测试

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

  • 相关阅读:
    Vue.js之Vue计算属性、侦听器、样式绑定
    Vue之初识Vue
    JS对象与Dom对象与jQuery对象之间的区别
    JavaScript之JS的数据类型
    JS中toString()、toLocaleString()、valueOf()的区别
    【开源】基于 Flink 1.10.1 的 SQL 提交程序
    Flink 1.10 UDF 的一个小问题
    Flink 1.10 SQL 写 Hbase 数据无法写入hbase问题
    Flink SQL 双流 join demo
    Flink SQL 解析复杂(嵌套)JSON
  • 原文地址:https://www.cnblogs.com/scut-fm/p/3328616.html
Copyright © 2020-2023  润新知