我非得把那么漂亮的代码搞懂不可
OUSTER 里面有涉及TCP网络编程的东西,先把这一段代码搞搞清楚。
client_state poll_client(const client& c, const int timeout_sec) {
//上一句很直观,定义了一个函数,函数的返回值类型是client-state,函数名是poll_client,括号里面是参数。
fd_set rfds;
//FD_ZERO(fd_set *fdset);将指定的文件描述符集清空,在对文件描述符集合进行设置前,必须对其进行初始化,如果不清空,由于在系统分配内存空间后,通常并不作清空处理,所以结果是不可知的。简单讲就是把fd_set清零
FD_ZERO(&rfds);
//FD_SET(fd_set *fdset);用于在文件描述符集合中增加一个新的文件描述符。简单讲就是c.lidar_fd加入rfds
FD_SET(c.lidar_fd, &rfds);
//FD_SET(fd_set *fdset);用于在文件描述符集合中增加一个新的文件描述符。简单将就是把c.imu_fd加入rfds
FD_SET(c.imu_fd, &rfds);
timeval tv;
tv.tv_sec = timeout_sec;
tv.tv_usec = 0;
int max_fd = std::max(c.lidar_fd, c.imu_fd);
int retval = select(max_fd + 1, &rfds, NULL, NULL, &tv);
client_state res = client_state(0);
if (retval == -1 && errno == EINTR) {
res = EXIT;
} else if (retval == -1) {
std::cerr << "select: " << std::strerror(errno) << std::endl;
res = client_state(res | ERROR);
} else if (retval) {
//FD_ISSET(int fd,fd_set *fdset);用于测试指定的文件描述符是否在该集合中。
if (FD_ISSET(c.lidar_fd, &rfds)) res = client_state(res | LIDAR_DATA);
if (FD_ISSET(c.imu_fd, &rfds)) res = client_state(res | IMU_DATA);
}
return res;
}
系统提供select函数来实现多路复用输入/输出模型。原型:
#include <sys/time.h>
#include <unistd.h>
int select(int maxfd,fd_set *rdset,fd_set *wrset,fd_set *exset,struct timeval *timeout);
参数maxfd是需要监视的最大的文件描述符值+1;rdset,wrset,exset分别对应于需要检测的可读文件描述符的集合,可写文件描述符的集 合及异常文件描述符的集合。struct timeval结构用于描述一段时间长度,如果在这个时间内,需要监视的描述符没有事件发生则函数返回,返回值为0。
struct timeval结构:
struct timeval{
long tv_sec;//second
long tv_usec;//minisecond
}
fd_set set; FD_ZERO(&set); /* 将set清零 / FD_SET(fd, &set); / 将fd加入set / FD_CLR(fd, &set); / 将fd从set中清除 / FD_ISSET(fd, &set); / 如果fd在set中则真 */
-
可监控的文件描述符个数取决与sizeof(fd_set)的值。我这边服务 器上sizeof(fd_set)=512,每bit表示一个文件描述符,则我服务器上支持的最大文件描述符是512*8=4096。据说可调,另有说虽 然可调,但调整上限受于编译内核时的变量值。本人对调整fd_set的大小不太感兴趣,参考http://www.cppblog.com /CppExplore/archive/2008/03/21/45061.html中的模型2(1)可以有效突破select可监控的文件描述符上 限。
(2)将fd加入select监控集的同时,还要再使用一个数据结构array保存放到select监控集中的fd,一是用于再select 返回后,array作为源数据和fd_set进行FD_ISSET判断。二是select返回后会把以前加入的但并无事件发生的fd清空,则每次开始 select前都要重新从array取得fd逐一加入(FD_ZERO最先),扫描array的同时取得fd最大值maxfd,用于select的第一个 参数。
(3)可见select模型必须在select前循环array(加fd,取maxfd),select返回后循环array(FD_ISSET判断是否有时间发生)。
select函数返回值:负值:select错误
正值:某些文件可读写或出错
0:等待超时,没有可读写或错误的文件
跟据我的理解,这段代码的功能是要实现一个能否返回LIDAR_DATA 以及 IMU_DATA的功能。
如果有错误,还请留言指点。