首页 > 代码库 > 《UNIX网络编程》之read_timeout实验

《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);结果为:成功

 

《UNIX网络编程》之read_timeout实验