• 《UNIX网络编程》之read_timeout实验


    最近在做项目,需要做一个服务器和客户端的基于TCP的套接口网络编程,由于服务器端返回数据并不是那么的及时,因此,需要在客户端做些延迟,然后才能去读取数据,实验测试结果如下。

    首先,我们先来看一下我们封装好的一个读延时函数:

    #define ERR_EXIT(m) 
            do 
            { 
                perror(m); 
                exit(EXIT_FAILURE); 
            }while(0)
    
    
    /**
     * read timeout - 读超时检测函数,不含读操作
     * @fd: 文件描述符
     * @wait_seconds: 等待超时秒数,如果为0标识不检测超时
     * 成功(未超时)返回0, 失败返回-1, 超时返回-1并且errno = ETIMEOUT
     */
    int read_timeout(int fd, unsigned int wait_seconds)
    {
        int ret;
        if(wait_seconds > 0)
        {
            fd_set read_fdset;
            struct timeval timeout;
    
            FD_ZERO(&read_fdset);
            FD_SET(fd, &read_fdset);
    
            timeout.tv_sec = wait_seconds;
            timeout.tv_usec = 0;
    
            do
            {
                ret = select(fd + 1, &read_fdset, NULL, NULL, &timeout);
            }while(ret < 0 && errno == EINTR);
    
            if(ret == 0)//fail
            {
                //time out.
                ret = -1;
                errno = ETIMEDOUT;
            }
            else if(ret == 1)//success
            {
                ret = 0;
            }
        }
        return ret;
    }

    下面,我们介绍如何使用该函数,伪代码如下:

    int ret = read_timeout(sockfd, 15);

    if(ret == 0)

    {

      readnum = read(sockfd, recvbuff, sizeof(recvbuff));

    }

    else if(ret == -1 && errno == ETIMEDOUT)

    {

    //time out dealing.

    }

    好,现在继续看我的服务器与客户端程序:

    服务器

    void str_echo(int sock)
    {
        ssize_t n;
        char buff[1024];
    
        again:
        while( (n = read(sock, buff, sizeof(buff))) > 0)
        {
            fputs(buff, stdout);
            sleep(3);//for testing client read_timeout
            write(sock, buff, n);
        }
        if(n < 0 && errno == EINTR)
        {
            goto again;
        }
        else if(n < 0)
        {
            ERR_EXIT("read");
        }
    }
    
    int main()
    {
        int listenfd, connfd;
        pid_t childpid;
        socklen_t clilen;
        struct sockaddr_in servaddr, cliaddr;
        
        if( (listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
        {
            ERR_EXIT("socket");
        }
    
        memset(&servaddr, 0, sizeof(servaddr));
        servaddr.sin_family = AF_INET;
        servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
        servaddr.sin_port = htons(5188);
    
        if((bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr))) < 0)
        {
            ERR_EXIT("bind");
        }
    
        if( (listen(listenfd, SOMAXCONN)) < 0)
        {
            ERR_EXIT("listen");
        }
    
        for(;;)
        {
            clilen = sizeof(cliaddr);
            connfd = accept(listenfd, (struct sockaddr*)&cliaddr, &clilen);
            if(connfd < 0)
            {
                ERR_EXIT("connect");
            }
    
            if( (childpid = fork()) == 0)
            {
                //child
                close(listenfd);
                str_echo(connfd);
                exit(0);
            }
            else
            {
                //parent
                close(connfd);
            }
    
        }
    }

    客户端

    void str_cli(int sock)
    {
        char sendbuff[1024];
        char recvbuff[1024];
    
        memset(sendbuff, 0, sizeof(sendbuff));
        memset(recvbuff, 0, sizeof(recvbuff));
        int ret = -1;
    
        //ssize_t n;
        while(fgets(sendbuff, sizeof(sendbuff), stdin) != NULL)
        {
            write(sock, sendbuff, strlen(sendbuff));    
    
            ret = read_timeout(sock, 15);
            if(ret == 0)
            {
                read(sock, recvbuff, sizeof(recvbuff));
            }
            else if(ret == -1 && errno == ETIMEDOUT)
            {
                ERR_EXIT("read_timeout");
            }
            fputs(recvbuff, stdout);
        }
    }
    
    
    
    int main(int argc, char **argv)
    {
        
        int sockfd;
        struct sockaddr_in servaddr;
        memset(&servaddr, 0, sizeof(servaddr));
        servaddr.sin_family = AF_INET;
        servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
        servaddr.sin_port = htons(5188);
    
        sockfd = socket(AF_INET, SOCK_STREAM, 0);
        if(sockfd < 0)
        {
            ERR_EXIT("socket");
        }
    
        if( (connect(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr))) < 0)
        {
            ERR_EXIT("connect");
        }
    
        str_cli(sockfd);
        return 0;
    }

    例子一:

    服务器延时3s, 客户端read_timeout(socd, 5);结果为:成功

  • 相关阅读:
    Python3 WebDriver操作cookie的方法
    Windows创建定时任务执行Python脚本
    Python3 自定义请求头消息headers
    为什么SQL用UPDATE语句更新时更新行数会多3行有触发器有触发器有触发器有触发器有触发器有触发器
    【C#】C#获取文件夹下的所有文件
    jQuery.ajax()调用asp.net后台方法(非常重要)
    Asp.Net+JQuery.Ajax之$.post
    c# post 接收传来的文件
    C#使用GET、POST请求获取结果,这里以一个简单的用户登陆为例。
    javascript中let和var的区别
  • 原文地址:https://www.cnblogs.com/wiessharling/p/4045305.html
Copyright © 2020-2023  润新知