超时设置方法( the way to set timeout )
来源:互联网 发布:boost高并发网络框架 编辑:程序博客网 时间:2024/05/18 00:01
Tips:
In the connection between the server and the client. Sometimes there may have some timeout. Today , we used our own method to realise a series of timeout function , including read_timeout , write_timeout , accept_timeout and connect_timeout which is the most difficult in four of them. We need to understand the different processing method of the timeout.
Client :
/************************************************************************ > filename : echocli.c > Author: ma6174 > Mail: ma6174@163.com > Created Time: Thu 29 Oct 16:38:57 2015 ************************************************************************/#include <fcntl.h>#include <stdio.h>#include <sys/socket.h>#include <string.h>#include <arpa/inet.h>#include <stdlib.h>#include <unistd.h>#include <errno.h>#include <signal.h>#define ERR_EXIT(m) \do \{\perror(m) ;\exit(EXIT_FAILURE) ;\}while(0) /* * read timeout -- * the function to test read timeout , not including read function. * fd : file descriptor * wait_senconds : the time to wait timeout,0 means that doesn't test timeout * success(not timeout) return 0 ; failed return -1 with timeout return -1 * errno = ETIMEOUT */int read_timeout ( int fd , unsigned int wait_seconds ) {int ret ;ret = 0 ;if ( wait_seconds > 0 ) {fd_set read_fdset ;struct timeval timeout ;FD_ZERO (&read_fdset ) ;FD_SET ( fd , &read_fdset ) ;timeout.tv_sec = wait ( wait_seconds ) ;timeout.tv_usec = 0 ;do {ret = select ( fd + 1 , &read_fdset , NULL , NULL , &timeout ) ;}while( ret < 0 && EINTR == errno ) ; // this occasion is interrupted by signal if ( 0 == ret ) {ret = -1 ;errno = ETIMEDOUT ;}else if ( 1 == ret ) // fd creats an readable event {ret = 0 ;}}return ret ;}/** * write_timeout write timeout function , no including write * fd : file descriptor * wait_seconds : the time to wait timeout , if 0 = wait senconds means that it doesn't test timeout * success(not timeout) return 0 ; failed return -1 with timeout return -1 */ int write_timeout ( int fd , unsigned int wait_seconds ) {int ret ; ret = 0 ;if ( wait_seconds > 0 ) {fd_set write_fdset ;struct timeval timeout ;FD_ZERO ( &write_fdset ) ;FD_SET ( fd , &write_fdset ) ;timeout.tv_sec = wait_seconds ;timeout.tv_usec = 0 ;do {ret = select ( fd + 1 , NULL ,&write_fdset , NULL , &timeout ) ;}while(ret < 0 && EINTR == errno ) ;if ( 0 == ret ) {ret = -1 ;errno = ETIMEDOUT ;}else if ( 1 == ret ) {ret = 0 ;}}return ret ;}/** * accept timeout with the accept function * fd : socket * addr : output parameter , return peer addr * wait_seconds : wait the time of timeout , if 0 = timeout means that it's the normal occassion * success(not timeout) return the connected socket; when it's timeout return -1 withe errno = ETIMEOUT */int accept_timeout ( int fd , struct sockaddr_in *addr , unsigned int wait_seconds ) {int ret ;ret = 0 ; socklen_t addrlen = sizeof(struct sockaddr_in ) ;if ( wait_seconds > 0 ) {fd_set accept_fdset ;struct timeval timeout ;FD_ZERO ( &accept_fdset ) ;FD_SET ( fd , &accept_fdset ) ;timeout.tv_sec = wait_seconds ;timeout.tv_usec = 0 ;do {ret = select ( fd + 1 , &accept_fdset , NULL ,NULL , &timeout ) ;}while(ret < 0 && EINTR == errno ) ;if ( -1 == ret ) {return -1 ; }else if ( 0 == ret ) {errno = ETIMEDOUT ;return -1 ;}}if ( NULL != addr ) {ret = accept ( fd , ( struct sockaddr*) addr , &addrlen ) ;}else {ret = accept ( fd , NULL , NULL ) ;}if ( -1 == ret ) {ERR_EXIT("accept") ;}return ret ;}/** * activate_nonblock * fd : file descriptor */void activate_nonblock ( int fd ) {int ret ;int flags = fcntl ( fd , F_GETFL ) ;//fcnt1 get the flag of fd.if ( -1 == flags ) {ERR_EXIT("fcnt1") ;}flags |= O_NONBLOCK ; // add non_block model ret = fcntl ( fd , F_SETFL , flags ) ;if ( -1 == ret ) {ERR_EXIT ("fcnt1") ;}}/** * deactivate_nonblack * fd : file descriptor */void deactivate_nonblock ( int fd ) {int ret ;int flags = fcntl ( fd , F_GETFL ) ;if ( -1 == flags ) {ERR_EXIT ("fcnt1") ;}flags &= ~ O_NONBLOCK ; // remove nonblock to the block modelret = fcntl ( fd , F_SETFL , flags ) ; if ( -1 == ret ) {ERR_EXIT ("fcnt1") ;}}/** * connect_timout -connect * fd : socket * addr: the peer address that we need to connect * wait_seconds : the time which is the timeout, if 0 = wait_seconds it means normal. * sucdess (it is not timeout ) return 0 ; failed return -1 with errno = ETIMEOUT */int connect_timeout ( int fd , struct sockaddr_in *addr , unsigned int wait_seconds ) {int ret ;socklen_t addrlen = sizeof(struct sockaddr_in );if ( wait_seconds > 0 ) {activate_nonblock(fd) ;}ret = connect ( fd , ( struct sockaddr*)addr , addrlen ) ; if ( ret < 0 && EINPROGRESS == errno ) {printf ("AAAAAAAAAAAAA\n") ;fd_set connect_fdset ;struct timeval timeout ;FD_ZERO ( &connect_fdset ) ;FD_SET ( fd , &connect_fdset ) ;timeout.tv_sec = wait_seconds ;timeout.tv_usec = 0 ; do {// once connected , the socket is writableret = select ( fd + 1 , NULL , &connect_fdset , NULL , &timeout ) ;}while( ret < 0 && EINTR == errno ) ;if ( 0 == ret ) // timeout {ret = -1 ;errno = ETIMEDOUT ;}else if ( ret < 0 ) // ret < 0 && EINTR != errno which means there is a mistake in socket. {return -1 ;}else if ( 1 == ret ) {/* ret = 1 means two occassion , one is the connection is successful. the other is that the connection has some mistakes. When there is a mistake in the socket , the failed information(but this kind of mistake would not influence select function)wouldn's save in the errno , we need to use the getsockopt to get it. */printf ("BBBBBBBBBBB\n") ;int err ;socklen_t socklen = sizeof(err) ;int sockopt_ret = getsockopt ( fd , SOL_SOCKET , SO_ERROR , &err , &socklen ) ;if ( -1 == sockopt_ret ) {return -1 ;}if ( 0 == err ) // no error , the connection is established. {printf ("DDDDDDDDDDDDDDD\n") ;ret = 0 ;}else // the socket has a mistake{printf ("CCCCCCCCCCCC\n") ;errno = err ;ret = -1 ;}}}if ( wait_seconds > 0 ) {deactivate_nonblock(fd) ;}return ret ;}int main (void) {int sock ;if ( ( sock = socket ( PF_INET , SOCK_STREAM , IPPROTO_TCP ) ) < 0 ) {ERR_EXIT("socket") ;}struct sockaddr_in servaddr ;memset ( &servaddr , 0 , sizeof(servaddr) ) ;servaddr.sin_family = PF_INET ;servaddr.sin_port = htons(5188) ;servaddr.sin_addr.s_addr = inet_addr("127.0.0.1") ;int ret = connect_timeout ( sock , &servaddr , 5 ) ; // timeout = 5 if ( -1 == ret && ETIMEDOUT == errno ) {printf ("timeout ...\n") ;return 1 ;}else if ( -1 == ret ) {ERR_EXIT("connect_timeout") ;}struct sockaddr_in localaddr ;socklen_t addrlen = sizeof(localaddr) ;if ( getsockname ( sock , ( struct sockaddr*) &localaddr , &addrlen ) < 0 ) {ERR_EXIT ("getsockname") ;}printf ("ip = %s port = %d\n" , inet_ntoa(localaddr.sin_addr) , ntohs(localaddr.sin_port) ) ;return 0 ; }
Server :
/************************************************************************ > filename: echocli.c > Author: ma6174 > Mail: ma6174@163.com > Created Time: Thu 29 Oct 16:38:57 2015 ************************************************************************/#include <sys/select.h>#include <sys/types.h>#include <signal.h>#include <stdio.h>#include <sys/socket.h>#include <string.h>#include <arpa/inet.h>#include <stdlib.h>#include <unistd.h>#include <errno.h>#include <sys/wait.h>#define ERR_EXIT(m) \do \{\perror(m) ;\exit(EXIT_FAILURE) ;\}while(0) int main(void) {int listenfd ;if ( (listenfd = socket(PF_INET , SOCK_STREAM , 0 ) ) < 0 ) {ERR_EXIT("socket") ;}struct sockaddr_in servaddr ;memset ( &servaddr , 0 , sizeof(servaddr) ) ;servaddr.sin_family = AF_INET ;servaddr.sin_port = htons(5188) ;servaddr.sin_addr.s_addr = htonl(INADDR_ANY) ;int on = 1 ;if ( setsockopt ( listenfd , SOL_SOCKET , SO_REUSEADDR , &on , sizeof(on) ) < 0 ) {ERR_EXIT("setsockopt") ;}if ( bind ( listenfd , ( struct sockaddr* ) &servaddr , sizeof(servaddr) ) < 0 ) {ERR_EXIT("bind") ;}if ( listen ( listenfd , SOMAXCONN ) < 0 ) {ERR_EXIT("listen") ;}struct sockaddr_in peeraddr ;socklen_t peerlen ;peerlen = sizeof(peeraddr) ;int conn ;if ( ( conn = accept ( listenfd , ( struct sockaddr* ) &peeraddr , &peerlen ) ) < 0 ) {ERR_EXIT("accept") ;}printf ("ip = %s port = %d\n" , inet_ntoa(peeraddr.sin_addr) , ntohs(peeraddr.sin_port) ) ;return 0 ;}
0 0
- 超时设置方法( the way to set timeout )
- 设置超时,timeout,socket
- 20.2.3.Setting the Login Timeout设置登录超时时间
- expect set timeout -1 永不超时
- the way to expert
- The way to CLI
- the way to happiness
- The way to go !
- [VB.NET]设置remoting超时timeout代码
- weblogic设置session-timeout超时时间
- python TCPServer, StreamRequestHandler设置超时时间timeout
- jQuery ajax $.get或$.post 实现timeout超时设置的方法
- Siebel Config: How to set Session Timeout?
- Way to avoid ssh connection timeout & freezing of terminal tab
- Way to avoid ssh connection timeout & freezing of terminal tab
- The way to describe bug.
- The quick way to CPIO
- The quick way to TAR
- 程序员的Job Security - 我的OJ(Online Judge)比较
- 字符串之旋转词
- ajax网络请求时候的data参数应该用JSON.stringify?
- 辛星浅析ruby下的mkmf.rb can't find header files for ruby at
- virsual box共享文件夹
- 超时设置方法( the way to set timeout )
- 论 为啥把博客从163搬家到CSDN
- 在Ubuntu中通过安装Nautilus实现鼠标右键打开Terminal
- 在Ubuntu 12.04环境下安装ffmpeg并实时转发视频流
- 程序员的Job Security 之 信心来源
- Fragment生命周期
- 装系统更改磁盘GPT
- Android studio制作APP调用浏览器
- 【Cocos2d-x 3.x】内存管理机制与源码分析