当前位置:   article > 正文

超时设置方法( the way to set timeout )_timeout.tv_sec

timeout.tv_sec

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 : 

  1. /************************************************************************
  2. > filename : echocli.c
  3. > Author: ma6174
  4. > Mail: ma6174@163.com
  5. > Created Time: Thu 29 Oct 16:38:57 2015
  6. ************************************************************************/
  7. #include <fcntl.h>
  8. #include <stdio.h>
  9. #include <sys/socket.h>
  10. #include <string.h>
  11. #include <arpa/inet.h>
  12. #include <stdlib.h>
  13. #include <unistd.h>
  14. #include <errno.h>
  15. #include <signal.h>
  16. #define ERR_EXIT(m) \
  17. do \
  18. {\
  19. perror(m) ;\
  20. exit(EXIT_FAILURE) ;\
  21. }while(0)
  22. /*
  23. * read timeout --
  24. * the function to test read timeout , not including read function.
  25. * fd : file descriptor
  26. * wait_senconds : the time to wait timeout,0 means that doesn't test timeout
  27. * success(not timeout) return 0 ; failed return -1 with timeout return -1
  28. * errno = ETIMEOUT
  29. */
  30. int read_timeout ( int fd , unsigned int wait_seconds )
  31. {
  32. int ret ;
  33. ret = 0 ;
  34. if ( wait_seconds > 0 )
  35. {
  36. fd_set read_fdset ;
  37. struct timeval timeout ;
  38. FD_ZERO (&read_fdset ) ;
  39. FD_SET ( fd , &read_fdset ) ;
  40. timeout.tv_sec = wait ( wait_seconds ) ;
  41. timeout.tv_usec = 0 ;
  42. do
  43. {
  44. ret = select ( fd + 1 , &read_fdset , NULL , NULL , &timeout ) ;
  45. }while( ret < 0 && EINTR == errno ) ; // this occasion is interrupted by signal
  46. if ( 0 == ret )
  47. {
  48. ret = -1 ;
  49. errno = ETIMEDOUT ;
  50. }
  51. else if ( 1 == ret ) // fd creats an readable event
  52. {
  53. ret = 0 ;
  54. }
  55. }
  56. return ret ;
  57. }
  58. /**
  59. * write_timeout write timeout function , no including write
  60. * fd : file descriptor
  61. * wait_seconds : the time to wait timeout , if 0 = wait senconds means that it doesn't test timeout
  62. * success(not timeout) return 0 ; failed return -1 with timeout return -1
  63. */
  64. int write_timeout ( int fd , unsigned int wait_seconds )
  65. {
  66. int ret ;
  67. ret = 0 ;
  68. if ( wait_seconds > 0 )
  69. {
  70. fd_set write_fdset ;
  71. struct timeval timeout ;
  72. FD_ZERO ( &write_fdset ) ;
  73. FD_SET ( fd , &write_fdset ) ;
  74. timeout.tv_sec = wait_seconds ;
  75. timeout.tv_usec = 0 ;
  76. do
  77. {
  78. ret = select ( fd + 1 , NULL ,&write_fdset , NULL , &timeout ) ;
  79. }while(ret < 0 && EINTR == errno ) ;
  80. if ( 0 == ret )
  81. {
  82. ret = -1 ;
  83. errno = ETIMEDOUT ;
  84. }
  85. else if ( 1 == ret )
  86. {
  87. ret = 0 ;
  88. }
  89. }
  90. return ret ;
  91. }
  92. /**
  93. * accept timeout with the accept function
  94. * fd : socket
  95. * addr : output parameter , return peer addr
  96. * wait_seconds : wait the time of timeout , if 0 = timeout means that it's the normal occassion
  97. * success(not timeout) return the connected socket; when it's timeout return -1 withe errno = ETIMEOUT
  98. */
  99. int accept_timeout ( int fd , struct sockaddr_in *addr , unsigned int wait_seconds )
  100. {
  101. int ret ;
  102. ret = 0 ;
  103. socklen_t addrlen = sizeof(struct sockaddr_in ) ;
  104. if ( wait_seconds > 0 )
  105. {
  106. fd_set accept_fdset ;
  107. struct timeval timeout ;
  108. FD_ZERO ( &accept_fdset ) ;
  109. FD_SET ( fd , &accept_fdset ) ;
  110. timeout.tv_sec = wait_seconds ;
  111. timeout.tv_usec = 0 ;
  112. do
  113. {
  114. ret = select ( fd + 1 , &accept_fdset , NULL ,NULL , &timeout ) ;
  115. }while(ret < 0 && EINTR == errno ) ;
  116. if ( -1 == ret )
  117. {
  118. return -1 ;
  119. }
  120. else if ( 0 == ret )
  121. {
  122. errno = ETIMEDOUT ;
  123. return -1 ;
  124. }
  125. }
  126. if ( NULL != addr )
  127. {
  128. ret = accept ( fd , ( struct sockaddr*) addr , &addrlen ) ;
  129. }
  130. else
  131. {
  132. ret = accept ( fd , NULL , NULL ) ;
  133. }
  134. if ( -1 == ret )
  135. {
  136. ERR_EXIT("accept") ;
  137. }
  138. return ret ;
  139. }
  140. /**
  141. * activate_nonblock
  142. * fd : file descriptor
  143. */
  144. void activate_nonblock ( int fd )
  145. {
  146. int ret ;
  147. int flags = fcntl ( fd , F_GETFL ) ; //fcnt1 get the flag of fd.
  148. if ( -1 == flags )
  149. {
  150. ERR_EXIT("fcnt1") ;
  151. }
  152. flags |= O_NONBLOCK ; // add non_block model
  153. ret = fcntl ( fd , F_SETFL , flags ) ;
  154. if ( -1 == ret )
  155. {
  156. ERR_EXIT ("fcnt1") ;
  157. }
  158. }
  159. /**
  160. * deactivate_nonblack
  161. * fd : file descriptor
  162. */
  163. void deactivate_nonblock ( int fd )
  164. {
  165. int ret ;
  166. int flags = fcntl ( fd , F_GETFL ) ;
  167. if ( -1 == flags )
  168. {
  169. ERR_EXIT ("fcnt1") ;
  170. }
  171. flags &= ~ O_NONBLOCK ; // remove nonblock to the block model
  172. ret = fcntl ( fd , F_SETFL , flags ) ;
  173. if ( -1 == ret )
  174. {
  175. ERR_EXIT ("fcnt1") ;
  176. }
  177. }
  178. /**
  179. * connect_timout -connect
  180. * fd : socket
  181. * addr: the peer address that we need to connect
  182. * wait_seconds : the time which is the timeout, if 0 = wait_seconds it means normal.
  183. * sucdess (it is not timeout ) return 0 ; failed return -1 with errno = ETIMEOUT
  184. */
  185. int connect_timeout ( int fd , struct sockaddr_in *addr , unsigned int wait_seconds )
  186. {
  187. int ret ;
  188. socklen_t addrlen = sizeof(struct sockaddr_in );
  189. if ( wait_seconds > 0 )
  190. {
  191. activate_nonblock(fd) ;
  192. }
  193. ret = connect ( fd , ( struct sockaddr*)addr , addrlen ) ;
  194. if ( ret < 0 && EINPROGRESS == errno )
  195. {
  196. printf ("AAAAAAAAAAAAA\n") ;
  197. fd_set connect_fdset ;
  198. struct timeval timeout ;
  199. FD_ZERO ( &connect_fdset ) ;
  200. FD_SET ( fd , &connect_fdset ) ;
  201. timeout.tv_sec = wait_seconds ;
  202. timeout.tv_usec = 0 ;
  203. do
  204. {
  205. // once connected , the socket is writable
  206. ret = select ( fd + 1 , NULL , &connect_fdset , NULL , &timeout ) ;
  207. }while( ret < 0 && EINTR == errno ) ;
  208. if ( 0 == ret ) // timeout
  209. {
  210. ret = -1 ;
  211. errno = ETIMEDOUT ;
  212. }
  213. else if ( ret < 0 ) // ret < 0 && EINTR != errno which means there is a mistake in socket.
  214. {
  215. return -1 ;
  216. }
  217. else if ( 1 == ret )
  218. {
  219. /* ret = 1 means two occassion , one is the connection is successful. the other
  220. is that the connection has some mistakes. When there is a mistake in the socket ,
  221. the failed information(but this kind of mistake would not influence select function)
  222. wouldn's save in the errno , we need to use the getsockopt to get it.
  223. */
  224. printf ("BBBBBBBBBBB\n") ;
  225. int err ;
  226. socklen_t socklen = sizeof(err) ;
  227. int sockopt_ret = getsockopt ( fd , SOL_SOCKET , SO_ERROR , &err , &socklen ) ;
  228. if ( -1 == sockopt_ret )
  229. {
  230. return -1 ;
  231. }
  232. if ( 0 == err ) // no error , the connection is established.
  233. {
  234. printf ("DDDDDDDDDDDDDDD\n") ;
  235. ret = 0 ;
  236. }
  237. else // the socket has a mistake
  238. {
  239. printf ("CCCCCCCCCCCC\n") ;
  240. errno = err ;
  241. ret = -1 ;
  242. }
  243. }
  244. }
  245. if ( wait_seconds > 0 )
  246. {
  247. deactivate_nonblock(fd) ;
  248. }
  249. return ret ;
  250. }
  251. int
  252. main (void)
  253. {
  254. int sock ;
  255. if ( ( sock = socket ( PF_INET , SOCK_STREAM , IPPROTO_TCP ) ) < 0 )
  256. {
  257. ERR_EXIT("socket") ;
  258. }
  259. struct sockaddr_in servaddr ;
  260. memset ( &servaddr , 0 , sizeof(servaddr) ) ;
  261. servaddr.sin_family = PF_INET ;
  262. servaddr.sin_port = htons(5188) ;
  263. servaddr.sin_addr.s_addr = inet_addr("127.0.0.1") ;
  264. int ret = connect_timeout ( sock , &servaddr , 5 ) ; // timeout = 5
  265. if ( -1 == ret && ETIMEDOUT == errno )
  266. {
  267. printf ("timeout ...\n") ;
  268. return 1 ;
  269. }
  270. else if ( -1 == ret )
  271. {
  272. ERR_EXIT("connect_timeout") ;
  273. }
  274. struct sockaddr_in localaddr ;
  275. socklen_t addrlen = sizeof(localaddr) ;
  276. if ( getsockname ( sock , ( struct sockaddr*) &localaddr , &addrlen ) < 0 )
  277. {
  278. ERR_EXIT ("getsockname") ;
  279. }
  280. printf ("ip = %s port = %d\n" , inet_ntoa(localaddr.sin_addr) , ntohs(localaddr.sin_port) ) ;
  281. return 0 ;
  282. }

Server : 

  1. /************************************************************************
  2. > filename: echocli.c
  3. > Author: ma6174
  4. > Mail: ma6174@163.com
  5. > Created Time: Thu 29 Oct 16:38:57 2015
  6. ************************************************************************/
  7. #include <sys/select.h>
  8. #include <sys/types.h>
  9. #include <signal.h>
  10. #include <stdio.h>
  11. #include <sys/socket.h>
  12. #include <string.h>
  13. #include <arpa/inet.h>
  14. #include <stdlib.h>
  15. #include <unistd.h>
  16. #include <errno.h>
  17. #include <sys/wait.h>
  18. #define ERR_EXIT(m) \
  19. do \
  20. {\
  21. perror(m) ;\
  22. exit(EXIT_FAILURE) ;\
  23. }while(0)
  24. int
  25. main(void)
  26. {
  27. int listenfd ;
  28. if ( (listenfd = socket(PF_INET , SOCK_STREAM , 0 ) ) < 0 )
  29. {
  30. ERR_EXIT("socket") ;
  31. }
  32. struct sockaddr_in servaddr ;
  33. memset ( &servaddr , 0 , sizeof(servaddr) ) ;
  34. servaddr.sin_family = AF_INET ;
  35. servaddr.sin_port = htons(5188) ;
  36. servaddr.sin_addr.s_addr = htonl(INADDR_ANY) ;
  37. int on = 1 ;
  38. if ( setsockopt ( listenfd , SOL_SOCKET , SO_REUSEADDR , &on , sizeof(on) ) < 0 )
  39. {
  40. ERR_EXIT("setsockopt") ;
  41. }
  42. if ( bind ( listenfd , ( struct sockaddr* ) &servaddr , sizeof(servaddr) ) < 0 )
  43. {
  44. ERR_EXIT("bind") ;
  45. }
  46. if ( listen ( listenfd , SOMAXCONN ) < 0 )
  47. {
  48. ERR_EXIT("listen") ;
  49. }
  50. struct sockaddr_in peeraddr ;
  51. socklen_t peerlen ;
  52. peerlen = sizeof(peeraddr) ;
  53. int conn ;
  54. if ( ( conn = accept ( listenfd , ( struct sockaddr* ) &peeraddr , &peerlen ) ) < 0 )
  55. {
  56. ERR_EXIT("accept") ;
  57. }
  58. printf ("ip = %s port = %d\n" , inet_ntoa(peeraddr.sin_addr) , ntohs(peeraddr.sin_port) ) ;
  59. return 0 ;
  60. }


本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/225161
推荐阅读
相关标签
  

闽ICP备14008679号