UNIX网络编程——套接字I/O操作上的超时设置
来源:互联网 发布:淘宝hd最新版本 编辑:程序博客网 时间:2024/05/16 12:34
1、调用alarm(SIGALRM信号处理)
调用alarm,它在指定超时期满时产生SIGALRM信号。
(1)使用SIGALRM为connect设置超时:因为在多线程程序中处理信号非常困难,因此建议只是在未线程化程序 或 单线程化程序中使用该技术。
/* include connect_timeo */#include"unp.h"static voidconnect_alarm(int);int connect_timeo(int sockfd, const SA *saptr, socklen_t salen, int nsec){Sigfunc*sigfunc;intn;sigfunc = Signal(SIGALRM, connect_alarm); //为SIGALRM建立一个信号处理函数if (alarm(nsec) != 0) //调用alarm,设置调用者指定的秒数err_msg("connect_timeo: alarm was already set");if ( (n = connect(sockfd, saptr, salen)) < 0) { //调用connectclose(sockfd);if (errno == EINTR)errno = ETIMEDOUT;}alarm(0);/* turn off the alarm */ //关闭本进程的报警时钟Signal(SIGALRM, sigfunc);/* restore previous signal handler */ // 恢复原来的信号处理函数return(n);}static void connect_alarm(int signo) //为SIGALRM建立的信号处理函数{return;/* just interrupt the connect() */}void Connect_timeo_demo(int fd, const SA *sa, socklen_t salen, int sec){if (connect_timeo(fd, sa, salen, sec) < 0) //调用connect_timeoerr_sys("connect_timeo error");}
(2)使用SIGALRM为recvfrom设置超时:
#include"unp.h"static voidsig_alrm(int);void dg_cli(FILE *fp, int sockfd, const SA *pservaddr, socklen_t servlen){intn;charsendline[MAXLINE], recvline[MAXLINE + 1];Signal(SIGALRM, sig_alrm); // 为SIGALRM建立一个信号处理函数while (Fgets(sendline, MAXLINE, fp) != NULL) {Sendto(sockfd, sendline, strlen(sendline), 0, pservaddr, servlen);alarm(5); // 设置一个5秒钟超时if ( (n = recvfrom(sockfd, recvline, MAXLINE, 0, NULL, NULL)) < 0) { //如果recvfrom被我们的信号处理函数中断if (errno == EINTR)fprintf(stderr, "socket timeout\n");elseerr_sys("recvfrom error");} else { //如果读到来自服务器的一行文本alarm(0); //关闭本进程的报警时钟recvline[n] = 0;/* null terminate */Fputs(recvline, stdout);}}}static void sig_alrm(int signo) // 为SIGALRM建立的信号处理函数{return;/* just interrupt the recvfrom() */}
2、使用select内置时间限制
将I/O阻塞在select调用上,以此代替直接阻塞在read或者write调用上,并设置select内置时间限制。
#include"unp.h"intreadable_timeo(int fd, int sec){fd_setrset;struct timevaltv;FD_ZERO(&rset);FD_SET(fd, &rset); // 在描述符集只中打开给定的描述符tv.tv_sec = sec; // 把要设置的等待秒数设置在timeval结构中tv.tv_usec = 0;return(select(fd+1, &rset, NULL, NULL, &tv)); //等待描述符变为可读,或者发生超时/* 4> 0 if descriptor is readable */}/* end readable_timeo */intReadable_timeo(int fd, int sec){intn;if ( (n = readable_timeo(fd, sec)) < 0) // 调用readable_timeoerr_sys("readable_timeo error");return(n);}//使用、调用示例:voiddg_cli(FILE *fp, int sockfd, const SA *pservaddr, socklen_t servlen){ int n; char sendline[MAXLINE], recvline[MAXLINE + 1]; while (Fgets(sendline, MAXLINE, fp) != NULL) { Sendto(sockfd, sendline, strlen(sendline), 0, pservaddr, servlen); if (Readable_timeo(sockfd, 5) == 0) { fprintf(stderr, "socket timeout\n"); //调用Readable_timeo,直到Readable_timeo告知所关注的描述符变为可读,才调用recvfrom,用来保证recvfrom不会被阻塞 } else { n = Recvfrom(sockfd, recvline, MAXLINE, 0, NULL, NULL); recvline[n] = 0; /* null terminate */ Fputs(recvline, stdout); } }}
3、使用较新的SO_RCVTIMEO 和 SO_SNDTIMEO 套接字选项
(1)使用SO_RCVTIMEO套接字选项为recvfrom设置超时
本方法的优势在于一次设置,一旦设置到某个描述符,其超时设置将应用于该描述符上的所有读操作。
#include"unp.h"voiddg_cli(FILE *fp, int sockfd, const SA *pservaddr, socklen_t servlen){intn;charsendline[MAXLINE], recvline[MAXLINE + 1];struct timevaltv;tv.tv_sec = 5; //填入期望的超时值tv.tv_usec = 0;Setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); //设置SO_RCVTIMEO套接字选项,并指向timeval结构tvwhile (Fgets(sendline, MAXLINE, fp) != NULL) {Sendto(sockfd, sendline, strlen(sendline), 0, pservaddr, servlen);n = recvfrom(sockfd, recvline, MAXLINE, 0, NULL, NULL);if (n < 0) {if (errno == EWOULDBLOCK) { //如果I/O操作超时,则recvfrom将返回一个EWOULDBLOCK错误fprintf(stderr, "socket timeout\n");continue;} elseerr_sys("recvfrom error");}recvline[n] = 0;/* null terminate */Fputs(recvline, stdout);}}
(2)SO_RCVTIMEO套接字选项仅仅应用于读操作, SO_SNDTIMEO 套接字选项仅仅应用于写操作。两者都不能用于设置connect超时。
0 0
- UNIX网络编程——套接字I/O操作上的超时设置
- UNIX网络编程——使用select 实现套接字I/O超时
- UNIX网络编程--设置I/O超时
- UNIX网络编程——设置套接字超时
- linux网络编程之套接字:套接字I/O超时设置方法和用select实现超时
- UNIX网络编程——非阻塞式I/O(套接字)
- linux网络编程之socket(十一):套接字I/O超时设置方法和用select实现超时
- linux网络编程之socket(十一):套接字I/O超时设置方法和用select实现超时
- linux网络编程之socket(十一):套接字I/O超时设置方法和用select实现超时
- linux网络编程之socket(十一):套接字I/O超时设置方法和用select实现超时
- linux网络编程之socket(十一):套接字I/O超时设置方法和用select实现超时
- Unix网络编程 高级IO套接字设置超时
- 网络编程中如何为I/O操作设置超时
- Linux下的socket编程实践(五)设置套接字I/O超时的方案
- 《Unix网络编程》卷1:套接字联网API(第3版):非阻塞I/O、ioctl操作、路由套接字
- UNIX网络编程——原始套接字的魔力【上】
- UNIX网络编程——原始套接字的魔力【上】
- UNIX网络编程——原始套接字的魔力【上】
- 学习UML实现、泛化、依赖、关联、聚合、组合
- jquery remove(),detach(),empty()
- 幸福
- 用JQuery实现Ajax的简单小应用
- MyEclipse10下Spring依赖注入的简单方法
- UNIX网络编程——套接字I/O操作上的超时设置
- HTTP与HTTPS的区别
- AngularUI Router
- VS2013调用armadillo使用KNN算法实现0-9数字分类
- 实战Apache+Tomcat集群和负载均衡
- iOS开发(OC)——根据url播放音频
- PCH文件的加载与宏定义
- [leetcode] 372. Super Pow 解题报告
- BlockingQueue