超时设置方法( the way to set timeout )
2015-11-09 02:28
323 查看
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 :
Server :
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 model ret = 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 writable ret = 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 ; }
相关文章推荐
- 论 为啥把博客从163搬家到CSDN
- ajax网络请求时候的data参数应该用JSON.stringify?
- 辛星浅析ruby下的mkmf.rb can't find header files for ruby at
- 字符串之旋转词
- 简单理解NIO
- [Angualr 2] Watch for changes
- 安卓新手的摸索之路
- hdoj2058(the sum problem
- python之模块distutils,打包工具
- 关系的幂运算
- SQLServer 扩展事件(Extended Events)
- [Angular 2] Custom Validtors
- 将.Net应用程序依赖的库文件部署到其他目录下
- 将.Net应用程序依赖的库文件部署到其他目录下
- Golang defer
- 如果想飞得高,就该把地平线忘掉
- [Angular 2] The form export from NgFormControl
- 你经常访问那些安卓网站?附 几百个技巧大全网址,电纸书网站,查开房隐私泄露网址等
- Deep learning:一 (基础知识_1)
- 欢迎使用CSDN-markdown编辑器