最近在做项目,需要做一个服务器和客户端的基于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);结果为:成功