在网络通信中,很多操作会使进程阻塞,
比如,TCP套接字中的read、send、recv、accept、connect等,以及UDP套接字中的recvfrom等。
超时检测的必要性:
— 避免进程在没有数据时无限制地阻塞
— 当设定的时间到时,进程从原操作返回继续运行
网络超时检测(一)
设置socket的属性 SO_RCVTIMEO,一次设置,管终身
1 /**** 设置socket的属性 SO_RCVTIMEO****/ 2 3 //参考代码: 4 struct timeval tv; 5 6 tv.tv_sec = 5; //设置5秒时间 7 tv.tv_usec = 0; 8 9 setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); //设置接收超时 10 11 recv() / recvfrom() //从socket读取数据
网络·超时检测(二)
用select检测socket是否“ready”
设置select函数的最后的参数是特定值,每次调用都需要重新赋值
,详见https://blog.csdn.net/lzjsqn/article/details/53790483
1 struct fd_set rfds; 2 struct timeval tv = (5, 0); //设置5秒时间 3 4 FD_ZERO(&rdfs); 5 FD_SET(sockfd, &rdfs); 6 7 if(select(sockfd+1, &rdfs, NULL, NULL, &tv) > 0) //socket就绪 8 { 9 recv() / recvfrom() //从socket读取数据 10 }
网络超时检测(三)
设置定时器(timer),捕捉SIGALRM信号
1 void handler(int signo) 2 { 3 return; 4 } 5 6 struct sigaction act; 7 sigaction(SIGALRM, NULL, &act); 8 act.sa_handler = handler; //处理函数 9 act.sa_flags &= ~SA_RESTART; //取反再与-->清除SA_RESTART标识位,系统就不会直接去读数据了。 10 sigaction(SIGALRM, &act, NULL); 11 alarm(5); //如果recv超过5秒没有信号来,定时器就触发SIGALRM信号,进而打断recv的阻塞 12 if(recv(......) < 0) ....
如何在Linux中动态检查到是否有网络以及网络中途的掉线 / 连接的检查
提示:
1、应用层
心跳检测,详见:网络程序中常用的三种心跳机制----服务器端
2、内核中
·网卡驱动中 2.6内核里面,使能1s的周期性检查定时器
·网卡硬件或者我们通过GPIO,插拔网线时候产生中断,处理相应中断 //立即检测到
心跳检测---方法一
数据交互双方隔一段时间,一方发送一点数据到对方,对方给出特定的应答。如超过设定次数大小的时间内还是没有应答,这时候认为异常
心跳检测---方法二
改变套接字的属性来实现
1 #include <netinet/tcp.h>//包含了SOL_TCP等宏的定义 2 void setKeepAlive(int sockfd,int attr_on,socklen_t idle_time,socklen_t interval,socklen_t cnt) 3 { 4 setsockopt(sockfd,SOL_SOCKET,SO_KEEPALIVE,(const char *)&attr_on,sizeof(attr_on)); 5 setsockopt(sockfd,SOL_TCP,TCP_KEEPIDLE,(const char *)&idle_time,sizeof(idle_time)); 6 setsockopt(sockfd,SOL_TCP,TCP_KEEPINTVL,(const char *)&interval,sizeof(interval)); 7 setsockopt(sockfd,SOL_TCP,TCP_KEEPCNT,(const char *)&cnt,sizeof(cnt)); 8 } 9 ...... 10 ...... 11 /*心跳检测(自动检测套接字连接是否已断开)*/ 12 int keepAlive = 1;//设定keepAlive 13 int keepIdle = 5;//开始首次keepAlive探测前的TCP空闲时间 14 int keepInterval = 5;//两次keepAlive探测间的时间间隔 15 int keepCount = 3;//判定断开前的keepAlive探测次数 16 17 setKeepAlive(newfd,keepAlive,keepIdle,keepInterval,keepCount); 18 ...... 19 ......