使用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. python pip安装三方库失败

    Collecting pip WARNING: Retrying (Retry(total=4, connect=None, read=None, redirect=None, status=None ...

  2. 替换yum源

    1.yum源进行备份 进入到yum源的配置文件中 执行命令如下:cd /etc/yum.repos.d 将yum源进行备份:mv Centos-Base.repo Centos-Base.repo.b ...

  3. Apache + PHP + Mysql Windows下配置

    1.安装Apache 下载网址 http://httpd.apache.org/download.cgi#apache24 二.下载php 下载地址:https://www.php.net/downl ...

  4. Leecode 206.反转链表(Java)

      想法: 1.设链表长度为n,如5,头节点head,则最后一个元素位置为head-1.      错误,发现行不通,此为链表非数组,存储位置不连续   2.设两个指针p,q,让p,q指向head,再 ...

  5. docker学习随笔

    总结自https://zhuanlan.zhihu.com/p/187505981 Linux内核提供了Namespace技术来隔离PID/IPC/网络资源等,还提供了Control Group(cg ...

  6. C#的Event事件

    一直不明白事件,今天写了一下,做个笔记吧. 先建一个类,里面有一个方法,返回bool型 public class Subject { public bool IsPass(int x) { Conso ...

  7. nacos实现Java和.NetCore的服务注册和调用

    用nacos作为服务注册中心,如何注册.NetCore服务,如何在Java中调用.NetCore服务呢?可以分为下面几个步骤: 0.运行nacos 1.开发.net core服务,然后调用nacos提 ...

  8. Linux邮件mail.rc配置,发件服务配置

    Linux邮件mail.rc配置 前提条件 邮箱需要开启smtp功能 关闭selinux和防火墙 1.  安装mailx yum install -y mailx 2.  配置/etc/mail.rc ...

  9. 针对于Sql server突然连接不到服务器的解决方法

    问题叙述 点击连接之后,总是会弹出一个错误弹窗: 方法解决 快捷键Win+R,输入services.msc,进入到服务界面: 找到SQL 代理(DEV) 将手动打开改成自动 再连接试一次 连上啦! ( ...

  10. Android笔记--选择按钮

    复选框CheckBox 具体实现: 注意: 开关按钮switch 具体实现: 单选按钮RadioButton 需要放到radioGroup里面写单选按钮 具体实现: