赞
踩
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 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 ;
- }
- /************************************************************************
- > 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 ;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。