当前位置: 首页 > news >正文

网络超时检测-11.9

应用场景
  • 在网络通信中,很多操作会使得进程阻塞:
    • TCP套接字中的recv/accept
    • UDP套接字中的recvfrom
  • 超时检测的必要性
    • 避免进程在没有数据时无限制地阻塞
    • 实现某些特定协议要求,比如某些设备规定,发送请求数据后,如果多长时间后没有收到来自设备的回复,需要做出一些特殊处理
  1. 自带超时参数的函数

如使用select/poll/epoll函数最后一个参数可以设置超时。

1)select设置超时

struct timeval tm = {2, 0};//设置2s打算阻塞
sret = select(maxfd + 1, &tempfds, NULL, NULL, &tm);
第五个参数:struct timeval {long    tv_sec;         /*秒*/long    tv_usec;        /*微秒*/};

2.poll

 int poll(struct pollfd *fds, nfds_t nfds, int timeout);
   第三个参数:时间单位是毫秒 -1阻塞, 2000=2s
   ret = poll(event, num, 2000);//超时检测时间为2s

3.epoll 设置的是epoll_wait


 int epoll_wait(int epfd, struct epoll_event *events,
                      int maxevents, int timeout);
  第四个参数:时间单位是毫秒 -1阻塞, 2000=2s
  ret = epoll_wait(epfd, events, 20, 2000);
设置超时后的返回值都为:<0  error
                        =0   超时
                        >0   正确 

2.利用setsockopt属性设置

Linux中socket属性

选项名称

说明

数据类型

 ====  SOL_SOCKET 应用层  ====

 SO_BROADCAST

       允许发送广播数据

 int

          SO_DEBUG

允许调试

int

SO_DONTROUTE

不查找路由

int

SO_ERROR

获得套接字错误

int

SO_KEEPALIVE

 保持连接

int

SO_LINGER

延迟关闭连接

 struct linger 

SO_OOBINLINE

带外数据放入正常数据流 

int 

SO_RCVBUF

接收缓冲区大小

int

SO_SNDBUF

发送缓冲区大小

int

SO_RCVLOWAT

接收缓冲区下限

int

SO_SNDLOWAT

发送缓冲区下限

 int 

SO_RCVTIMEO

接收超时

struct timeval

SO_SNDTIMEO

发送超时

struct timeval

SO_REUSEADDR

允许重用本地地址和端口

int

SO_TYPE

获得套接字类型

int 

SO_BSDCOMPAT

与BSD系统兼容

                   int

==== IPPROTO_IP  网络层 ====

  IP_HDRINCL

         在数据包中包含IP首部

 int

IP_OPTINOS

 IP首部选项

 int

IP_TOS

服务类型

int

IP_TTL

生存时间

int

IP_ADD_MEMBERSHIP

将指定的IP加入多播组

  struct ip_mreq

==== IPPRO_TCP 传输层 ====

TCP_MAXSEG

TCP最大数据段的大小

int 

TCP_NODELAY

不使用Nagle算法

 int 

功能:设置/获取网络属性;
原型:#include <sys/types.h>          /* See NOTES */#include <sys/socket.h>int getsockopt(int sockfd, int level, int optname,void *optval, socklen_t *optlen);int setsockopt(int sockfd, int level, int optname,
const void *optval, socklen_t optlen);
参数:int sockfd:指定要设置/获取哪个套接字的属性;int level:指定要控制的协议层次;
        SOL_SOCKET:应用层 通用套接字选项;  man 7 socket
        IPPROTO_TCP:TCP选项               man 7 TCP
        IPPROTO_UDP:UDP选项               man 7 UDP
        IPPROTO_IP:IP选项;                man 7 IPint optname:指定要控制的内容,指定控制方式;--- SOL_SOCKET: man 7 socket -----
        SO_REUSEADDR:允许端口快速重用   optval: int*
        SO_BROADCAST:允许广播          optval: int*   
        SO_RCVBUF/SO_SNDBUF:接收缓冲区 发送缓冲区大小
        SO_RCVTIMEO/SO_SNDTIMEO:接收超时时间,发送超时时间void *optval:根据optname不同,该类型不同;(数据类型socklen_t optlen/socklen_t *optlen:真实的optval指针指向的内存空间的大小;
返回值:
    成功,返回0
    失败,返回-1,更新errno;

3、利用alarm定时器设置

#include <unistd.h>
unsigned int alarm(unsigned int seconds);
功能:在进程中设置一个定时器
参数:seconds:定时时间,单位为秒
返回值:如果调用此alarm()前,进程中已经设置了闹钟时间,则
	返回上一个闹钟时间的剩余时间,否则返回0。alarm(5) 闹钟   定时器
//5秒之后会,会有一个信号产生(SIGALRM)
int sigaction(int signum, const struct sigaction *act,struct sigaction *oldact);
 功能:对接收到的指定信号处理
	signum  信号		 
struct sigaction 
{void     (*sa_handler)(int); //信号处理函数void     (*sa_sigaction)(int, siginfo_t *, void *);  //信号处理函数sigset_t   sa_mask;int        sa_flags;      //信号属性; SA_RESTART自重启属性
#define SA_RESTART  0x10000000void     (*sa_restorer)(void);};     //设置信号属性struct sigaction act;sigaction(SIGALRM,NULL,&act);//获取原属性
    act.sa_handler=handler;//修改属性sigaction(SIGALRM,&act,NULL);//将修改的属性设置回去注:在recv前调用alarm函数
   alarm的 SIGALRM信号产生后会打断(终端)下面的系统调用recv;
   打断后相当于recv错误返回。信号改变行为后,当前进程所有行为都被改变,若想要再次改变回原行为,需要再次执行sigaction.

注意:一个进程只能有一个闹钟时间。如果在调用alarm时已设置过闹钟时间,则之前的闹钟时间被新值所代替,时间到了会给进程发送一个SIGALRM信号,这个信号也有结束进程的功能

#include<stdio.h>
#include<signal.h>
#include<unistd.h>void handler(int sig)
{printf("timeout................\n");
}int main(int argc, char const *argv[])
{   struct sigaction act;sigaction(SIGALRM,NULL,&act);//获取原属性
    act.sa_handler=handler;//修改属性sigaction(SIGALRM,&act,NULL);//将修改的属性设置回去// sigaction(int signum, const struct sigaction *act,struct sigaction *oldact);char buf[64]={};while (1){   alarm(2);printf("hello\n");fgets(buf,sizeof(buf),stdin);printf("fgets阻塞接触\n");int ret=alarm(2);printf("%d\n",ret);read(0,buf,sizeof(buf));printf("read阻塞接触\n");printf("buf:%s\n",buf);}return 0;
}

相关文章:

  • 小米手环8pro重新和手机配对解决办法
  • 在Linux安装Nginx Proxy Manager并结合内网穿透工具实现远程访问管理界面
  • vscode+python开发之虚拟环境和解释器切换
  • git push 报错 The requested URL returned error: 500
  • 回顾——自我监督的 Vision Transformer 学到了什么?
  • CTFhub-RCE-过滤目录分隔符 /
  • 【owt】owt-p2p的vs工程构建
  • Mindomo Desktop for Mac(免费思维导图软件)下载
  • SDL音视频渲染
  • 深度学习之基于YoloV5血红细胞检测识别系统
  • (C语言)输入一个序列,判断是否为奇偶交叉数
  • Python基础入门----如何通过conda搭建Python开发环境
  • 学习笔记5——对象、直接内存、执行引擎,string
  • 猫罐头哪个牌子好?分享十款猫罐头品牌排行榜!
  • three.js相机调用reset方法复原但无法完全复原
  • [iOS]Core Data浅析一 -- 启用Core Data
  • 【vuex入门系列02】mutation接收单个参数和多个参数
  • 【跃迁之路】【519天】程序员高效学习方法论探索系列(实验阶段276-2018.07.09)...
  • 2017 年终总结 —— 在路上
  • CSS3 聊天气泡框以及 inherit、currentColor 关键字
  • ES10 特性的完整指南
  • Git初体验
  • Invalidate和postInvalidate的区别
  • iOS动画编程-View动画[ 1 ] 基础View动画
  • JS基础篇--通过JS生成由字母与数字组合的随机字符串
  • mysql外键的使用
  • PAT A1092
  • PHP的类修饰符与访问修饰符
  • Python语法速览与机器学习开发环境搭建
  • react 代码优化(一) ——事件处理
  • SpiderData 2019年2月16日 DApp数据排行榜
  • UEditor初始化失败(实例已存在,但视图未渲染出来,单页化)
  • Work@Alibaba 阿里巴巴的企业应用构建之路
  • 安装python包到指定虚拟环境
  • 短视频宝贝=慢?阿里巴巴工程师这样秒开短视频
  • 翻译 | 老司机带你秒懂内存管理 - 第一部(共三部)
  • 反思总结然后整装待发
  • 基于Android乐音识别(2)
  • 基于axios的vue插件,让http请求更简单
  • 力扣(LeetCode)357
  • 批量截取pdf文件
  • 格斗健身潮牌24KiCK获近千万Pre-A轮融资,用户留存高达9个月 ...
  • (11)工业界推荐系统-小红书推荐场景及内部实践【粗排三塔模型】
  • (4) PIVOT 和 UPIVOT 的使用
  • (DenseNet)Densely Connected Convolutional Networks--Gao Huang
  • (vue)页面文件上传获取:action地址
  • (顶刊)一个基于分类代理模型的超多目标优化算法
  • (二)pulsar安装在独立的docker中,python测试
  • (二)PySpark3:SparkSQL编程
  • (附源码)php投票系统 毕业设计 121500
  • (十二)devops持续集成开发——jenkins的全局工具配置之sonar qube环境安装及配置
  • (转)Sublime Text3配置Lua运行环境
  • (转)关于多人操作数据的处理策略
  • .FileZilla的使用和主动模式被动模式介绍
  • .form文件_SSM框架文件上传篇