关于select函数超时时间问题

关于select函数超时时间问题

select函数使用

int select(int n,fd_set * readfds,fd_set * writefds,fd_set * exceptfds,struct timeval * timeout);

具体参数说明:
1、 int n是一个整数值,是指集合中所有文件描述符的范围,即所有文件描述符的最大值加1,不能错!
2、fd_set *readfds是指向fd_set结构的指针,这个集合中应该包括文件描述符,我们是要监视这些文件描述符的读变化的,即我们关心是否可以从这些文件中读取数据了,如果这个集合中有一个文件可读,select就会返回一个大于0的值,表示有文件可读,如果没有可读的文件,则根据timeout参数再判断是否超时,若超出timeout的时间,select返回0,若发生错误返回负值。可以传入NULL值,表示不关心任何文件的读变化。
3、fd_set *writefds是指向fd_set结构的指针,这个集合中应该包括文件描述符,我们是要监视这些文件描述符的写变化的,即我们关心是否可以向这些文件中写入数据了,如果这个集合中有一个文件可写,select就会返回一个大于0的值,表示有文件可写,如果没有可写的文件,则根据timeout参数再判断是否超时,若超出timeout的时间,select返回0,若发生错误返回负值。可以传入NULL值,表示不关心任何文件的写变化。
4、 fd_set *errorfds同上面两个参数的意图,用来监视文件错误异常。
5、struct timeval *timeout是select的超时时间,这个参数至关重要,它可以使select处于三种状态,第一,若将NULL以形参传入,即不传入时间结构,就是将select置于阻塞状态,一定等到监视文件描述符集合中某个文件描述符发生变化为止;第二,若将时间值设为0秒0毫秒,就变成一个纯粹的非阻塞函数,不管文件描述符是否有变化,都立刻返回继续执行,文件无变化返回0,有变化返回一个正值;第三,timeout的值大于0,这就是等待的超时时间,即select在timeout时间内阻塞,超时时间之内有事件到来就返回了,否则在超时后不管怎样一定返回,返回值同上述。

关于select函数的使用,有几点需要注意的地方:
1. maxfdp 为所有fd中的最大值加1.
2. readfds 和 timeout 在每次执行select前都要重新初始化. 对于readfds,每次循环都要清空集合,否则不能检测描述符变化;而对于timeout,每次都要初始化其值,否则timeout被默认初始化为0。

//使用select函数的示例(程序段):
int Read(int fd, char *readbuf, int BUFSIZE)
{
  int len = 0;
  int nfds,select_ret;
  struct timeval timeout;
  fd_set readfds;
  FD_ZERO(&readfds);
  FD_SET(fd, &readfds); 
  nfds=fd+1;
  timeout.tv_sec = 1;
  timeout.tv_usec = 500000;
  while ((select_ret = select(nfds, &readfds, NULL, NULL, &timeout)) > 0)
  {
    len += read(fd, readbuf + len, BUFSIZE);
    FD_ZERO(&readfds);
    FD_SET(fd, &readfds); 
    nfds=fd+1;
    timeout.tv_sec = 0;
    timeout.tv_usec = 500000;
  }
  readbuf[len]='\0';

  return len;
}
### 设置 `select` 超时时间为 50 毫秒的方法 在 C/C++ 编程中,可以使用 `struct timeval` 来为 `select` 函数设置超时时间。具体来说,可以通过初始化一个 `timeval` 结构体并将其传递给 `select` 的最后一个参数来实现这一功能。 以下是详细的说明以及代码示例: #### 初始化 `struct timeval` `struct timeval` 定义如下: ```c struct timeval { long tv_sec; /* 秒 */ long tv_usec; /* 微秒 (范围: [0,999999]) */ }; ``` 为了设置 50 毫秒的超时时间,需要将 `tv_sec` 设为 0 表示无整数秒部分,并将 `tv_usec` 设为 50000(因为 1 秒等于 1000000 微秒)。[^1] #### 使用 `select` 函数 `select` 函数原型如下: ```c int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout); ``` 其中第五个参数即为超时时间指针。如果该参数不为空,则表示设置了超时时间;如果为空则表示无限期等待直到事件触发。当指定时间内没有任何就绪文件描述符时,`select` 将返回 0 并结束阻塞状态。 下面是完整的代码示例展示如何配置 `select` 的超时时间为 50 毫秒: ```c #include <stdio.h> #include <sys/select.h> #include <unistd.h> // 假设此函数用于创建服务器套接字 int socket_server_init(const char* ip, int port) { return 0; } int main() { int sockfd = socket_server_init("127.0.0.1", 8080); FD_SET(sockfd, &rfds); // 添加到读集合 struct timeval timeout; timeout.tv_sec = 0; // 零秒 timeout.tv_usec = 50000; // 五万微秒=五十毫秒 int ret = select(sockfd + 1, &rfds, NULL, NULL, &timeout); if(ret == -1){ perror("Select error"); }else if(ret == 0){ printf("Timeout occurred! No data after 50 milliseconds.\n"); } else{ if(FD_ISSET(sockfd,&rfds)){ printf("Data is available now.\n"); // 处理数据... } } close(sockfd); return 0; } ``` 上述程序片段展示了如何通过设定 `struct timeval` 实现对 `select` 的精确控制以满足特定需求下的短周期轮询或者防止长时间挂起等情况的发生。[^4] #### 注意事项 需要注意的是,在实际应用过程中可能还会遇到其他因素影响最终效果,比如系统负载过高可能导致精度下降等问题。因此建议开发者根据实际情况调整策略或考虑更高效的解决方案如 epoll 等替代品。[^3]
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值