zoukankan      html  css  js  c++  java
  • select使用实例——str_cli函数(修订版)

    我们可以使用select函数重写http://www.cnblogs.com/nufangrensheng/p/3587962.html中的str_cli函数,这样服务器进程一终止,客户就能马上得到通知。早先那个版本的问题在于:当套接口上发生某些事件时,客户可能阻塞于fgets调用。新版本改为阻塞于select调用,等待要么标准输入可读,要么套接口可读。下图展示了调用select所处理的各种条件。

    image

    客户的套接口上的三个条件处理如下:

    灯泡(i)如果对端TCP发送数据,那么该套接口变为可读,并且read返回一个大于0的值(即读入数据的字节数)。

    灯泡(ii)如果对端TCP发送一个FIN(对端进程终止),那么该头接口变为可读,并且read返回0(EOF)。

    灯泡(iii)如果对端TCP发送一个RST(对端主机崩溃并重新启动),那么该套接口变为可读,并且read返回-1,而errno中含有确切的错误代码。

    新版本源代码:

    #include <stdio.h>
    #include <sys/select.h>
    #include <sys/time.h>
    #include <errno.h>
    #include <stdlib.h>
    #include <string.h>
    
    int 
    max(int a, int b)
    {
        return(a >= b ? a : b);
    }
    
    void
    str_cli(FILE *fp, int sockfd)
    {
        int       maxfdpl;
        fd_set    rset;
        char      sendline[4096], recvline[4096];
    
        FD_ZERO(&rset);
        for(;;)
        {
            FD_SET(fileno(fp), &rset);
            FD_SET(sockfd, &rset);
            maxfdpl = max(fileno(fp), sockfd) + 1;
            if(select(maxfdpl, &rset, NULL, NULL, NULL) < 0)
            {
                perror("select");
                exit(1);
            }
            
            if(FD_ISSET(sockfd, &rset))    /* socket is readable */
            {
                if(readline(sockfd, recvline, 4096) == 0)
                {
                    printf("str_cli: server terminated prematurely
    ");
                    exit(1);
                }
                fputs(recvline, stdout);
            }
    
            if(FD_ISSET(fileno(fp), &rset)) /* input is readable */
            {
                if(fgets(sendline, 4096, fp) == NULL)
                    return;
                writen(sockfd, sendline, strlen(sendline));
            }
        }
    }

    调用select

    我们只需要一个用于检查可读性的描述字集。该集合由FD_ZERO初始化,并用FD_SET打开两位:一位对应于标准I/O文件指针fp,一位对应于套接口sockfd。fileno函数把标准I/O文件指针转换为对应的描述字。select和poll只工作在描述字上。

    计算出两个描述字中的较大值后,调用select。在该调用中,写集合指针和异常集合指针都是空指针。最后一个参数(时间限制)也是空指针,因为我们希望本调用阻塞到某个描述字就绪为止。

  • 相关阅读:
    EJB 笔记
    设计模式
    go 笔记
    破解ssl pinning 抓APP的https数据包
    python读取、写入csv文件
    Python中用正则匹配手机号码
    苹果手机安装charles证书
    mysql在表中插入一个字段
    Python递归调用自己的函数
    mysql查询语句
  • 原文地址:https://www.cnblogs.com/nufangrensheng/p/3589824.html
Copyright © 2011-2022 走看看