使用select需要注意的细节

在学校的时候就使用过select,但是在项目中使用的时候却犯了个错误。

select如何使用就不进行总结了,网上教程太多,以下是项目中我写的一小段代码,便于总结。

int TvsStateManager::handleProbeStreamMsg()
{
struct sockaddr_in addr;
int fd, n,addrlen;
struct ip_mreq mreq; char recvBuf[BUF_SIZE]; u_int flag = 1; /* create what looks like an ordinary UDP socket */
if ((fd=socket(AF_INET, SOCK_DGRAM, 0)) < 0){
LogE("creat socket failure\n");
return -1;
} /* allow multiple sockets to use the same PORT number */
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag)) < 0){
LogE("reusing addr failure\n");
return -2;
} /* set up destination address */
memset(&addr,0,sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY); /* N.B.: differs from sender */
addr.sin_port = htons(mConfig->mMultiCastStreamPort); /* bind to receive address */
if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0){
LogE("bind socket failure\n");
return -3;
} /* use setsockopt() to request that the kernel join a multicast group */
mreq.imr_multiaddr.s_addr = inet_addr(mConfig->mMultiCastStreamIP.c_str());
mreq.imr_interface.s_addr = htonl(INADDR_ANY); if (setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0){
LogE("setsockopt join multicast group failure\n");
return -4;
} // if(setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout)) < 0){
// LogE("set timeout failure\n");
// return -5;
// } fd_set readfds;
int maxfds = 0;
struct timeval timeout;
while (1){
/*这个超时设置很关键,必须设置在里面,因为select模式,timeout会随着检查文件描述符集合状态而减小,换句话说就是用剩余的时间来更新这个结构*/
timeout.tv_sec = 5;
timeout.tv_usec = 0;
addrlen=sizeof(addr);
FD_ZERO(&readfds);
FD_SET(fd,&readfds);
maxfds = fd +1;
if(select(maxfds, &readfds, NULL, NULL, &timeout) > 0){ if((n = recvfrom(fd, recvBuf, BUF_SIZE, 0, (struct sockaddr *)&addr, &addrlen)) > 0){
mProbeStream = true;
mQtPanel->sendProbeStreamMsg(mProbeStream);
}
bzero(recvBuf,sizeof(recvBuf));
if(setsockopt(fd, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq)) < 0){
LogE("setsockopt quit multicast failure\n");
return -7;
}
close(fd);
break;
}
} return 0;
}

可以看到我在使用结构struct timeval,将timeout设置放到了while里面,这样才是正确的。可能也是由于自己以前理解的不够透彻,当时我把设置timeout放到了while外面,那么引起的结果就是程序只等待一次5秒,后面却一直显示timeout不在等待5秒,测试程序就不再弄了。重新翻阅了下《unix环境高级编程》这本书,有一段不起眼的话说的很详细,如下:

POSIX.1允许实现修改timeval结构中的值,所以在select返回后,你不能指望该结构仍旧保持调用select之前它所包含的值。FreeBSD 8.0、Mac OS X 10.6.8和Solaris 10都保持该结构中的值不变。但是,若在超时时间尚未到期时,select就返回,那么Linux 3.2.0将用剩余时间值更新该结构。

这段话已经很明确了,select设置的时间是会随着改变的,另外如果想不让它改变,那么可以使用pselect函数,而且pselect函数超时更加精确,pselect使用的是timespec结构,timespec以秒和纳秒表示超时值,而select的timeval结构则是秒和微妙级别。另外pselect的超时值是被设置为const的,这也就保证了调用pselect不会改变此值。

使用select需要注意的细节的更多相关文章

  1. Mybatis select、insert、update、delete 增删改查操作

    MyBatis 是支持普通 SQL 查询,存储过程和高级映射的优秀持久层框架. MyBatis 消除了几乎所有的 JDBC 代码和参数的手工设置以及对结果集的检索.MyBatis 可以使用简单的XML ...

  2. mybatis的select、insert、update、delete语句

    一.select <!-- 查询学生,根据id --> <select id="getStudent" parameterType="String&qu ...

  3. 转:mybatis——select、insert、update、delete

    一.select <!-- 查询学生,根据id --> <select id="getStudent" parameterType="String&qu ...

  4. SQL 提高查询效率

    1.关于SQL查询效率,100w数据,查询只要1秒,与您分享: 机器情况p4: 2.4内存: 1 Gos: windows 2003数据库: ms sql server 2000目的: 查询性能测试, ...

  5. iOS开发之SQLite-C语言接口规范(二) —— Prepared Your SQL Statements

    在<SQLite的C语言接口规范(一)>中介绍了如何去连接打开数据库,本篇博客就介绍如何操作数据库,本篇主要给出了如何执行数据库查询语句(Select), 然后遍历结果集.本篇博客就直接使 ...

  6. SQL语句执行效率及分析(note)

    1.关于SQL查询效率,100w数据,查询只要1秒,与您分享: 机器情况p4: 2.4内存: 1 Gos: windows 2003数据库: ms sql server 2000目的: 查询性能测试, ...

  7. MyBatis学习(二)、SQL语句映射文件(2)增删改查、参数、缓存

    二.SQL语句映射文件(2)增删改查.参数.缓存 2.2 select 一个select 元素非常简单.例如: <!-- 查询学生,根据id --> <select id=" ...

  8. MyBatis详解 与配置MyBatis+Spring+MySql

    MyBatis 是一个可以自定义SQL.存储过程和高级映射的持久层框架.MyBatis 摒除了大部分的JDBC代码.手工设置参数和结果集重获.MyBatis 只使用简单的XML 和注解来配置和映射基本 ...

  9. 二、SQL语句映射文件(2)增删改查、参数、缓存

    //备注:该博客引自:http://limingnihao.iteye.com/blog/106076 2.2 select 一个select 元素非常简单.例如: Xml代码 收藏代码 <!- ...

  10. 详解Java的MyBatis框架中SQL语句映射部分的编写

    这篇文章主要介绍了Java的MyBatis框架中SQL语句映射部分的编写,文中分为resultMap和增删查改实现两个部分来讲解,需要的朋友可以参考下 1.resultMap SQL 映射XML 文件 ...

随机推荐

  1. data location nextcloud

    /var/snap/nextcloud/common/nextcloud/data/ Adding files to Nextcloud using the command line https:// ...

  2. Altium Designer在原理图中复制报错InvalidParameter解决

    Altium Designer 原理图复制出现  InvalidParameter Exception Occurred In Copy    解决方案为将下图红框中的√去掉 将红框中√去掉就点击右下 ...

  3. 【前端样式】关于Element-plus 菜单 unique-opened不生效的问题

    需要保证el-sub-menu 的唯一性,即index得写在el-sub-menu上,否则 unique-opened 属性不生效.

  4. 全新TI AM62xx系列核心板上市,小小身板蕴藏巨大势能!

    2011年TI推出AM335x,成为了此后市场上最受欢迎的通用工业级ARM处理器,并广泛应用于工业HMI, 医疗电子,机器人,能源,汽车等领域.随着工业4.0的发展,HMI人机交互.工业工控.医疗等领 ...

  5. 6 Sampling Configuration Space: 6.4 Adaptive Steered Molecular Dynamics

    6.4 Adaptive Steered Molecular Dynamics 理论背景: SMD 利用施加steering力的伪粒子,以便以特定速度穿过反应坐标. 这个外力允许人们在MD模拟时间尺度 ...

  6. 使用react-vite-antd,修改antd主题,报错 [vite] Internal server error: Inline JavaScript is not enabled. Is it set in your options? It is hacky way to make this function will be compiled preferentially by less

    一般报错 在官方文档中,没有关于vite中如何使用自定义主题的相关配置,经过查阅 1.安装less  yarn add less (已经安装了就不必再安装) 2.首先将App.css改成App.les ...

  7. 不使用setTimeout的延迟执行

    function sleep(ms){ var time = new Date(); time.setTime(time.getTime() + ms); while(new Date().getTi ...

  8. iframe跨域通信window.postMessage()方法

    需求:A页面中要嵌入一个iframe,这个iframe是B页面,此时A页面需要得到B页面的一些信息. window.postMessage() 我们都知道浏览器的同源策略,即对于两个不同页面的脚本,只 ...

  9. Spring--bean管理(easy)

    bean作用范围 利用同一个BookDao设置出来两个不同的对象,得到相同的地址: (默认为单例,即表现为同一个地址) 要是想要得到不同的地址,就需要我们在接口实现类的上面加上这样一个注解:(双例) ...

  10. RunnerGo相较于Jmeter优劣势分析

    RunnerGo是一款基于go语言研发的开源测试平台.在这里我想从性能测试方面.结构方面以及功能方面对比两款产品. 性能方面: Runner基于go语言研发,相对于jmeter来说更轻量级.所以性能测 ...