1. select函數
select的作用:
輪詢的方式,從多個文件描述符中獲取狀態變化后的情況。
頭文件
#include <sys/time.h> //for struct timeval
#include <unistd.h> //for select
函數原型
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
參數解釋
- nfds: 要檢測的文件描述符的范圍,為文件最大描述符+1
- readfds: 包含所有可能因狀態變成可讀而觸發select函數返回的文件描述符
- writefds: 包含所有可能因狀態變成可寫而觸發select函數返回的文件描述符
- exceptfds: 包含所有可能因狀態發生異常而觸發select函數返回的文件描述符
void FD_CLR(int fd, fd_set *set); //將fd在set中去除
void FD_SET(int fd, fd_set *set); //將fd添加到set中
int FD_ISSET(int fd, fd_set *set); //檢查set中fd是否有狀態變化
void FD_ZERO(fd_set *set); //清空整個set
- timeout:
struct timeval {
long tv_sec; /* seconds */
long tv_usec; /* microseconds */
};
返回值
當超時或其中一個/多個文件描述符發生變化時,此函數將返回,返回值:
- -1: 函數執行出錯
- 0: 超時,並將時間結構體清空為0
0: 狀態變化的文件描述符的個數
基本實例
fd_set rdfds;
struct timeval tv;
int rtn = 0;
FD_ZERO(&rdfds); //清空fd_set
FD_SET(socket, &rdfds); //將要檢測的socket描述符加入到fd_set集合中
tv.tv_sec = 2;
tv.tv_usec = 1000; //設置超時時間為2s+1ms
rtn = select(socket+1, &rdfds, NULL, NULL, &tv);
if(rtn < 0)
perror("select");
else if(0 == rtn)
printf("timeout\n");
else
{
printf("rtn = %d\n", rtn); //查看有多少個文件描述符發生了變化
if(FD_ISSET(socket, &rdfds)) //判斷下這個socket是否狀態真的變成了可讀
{
recv(...);
}
}
2. select做時間函數
void time_delay(int seconds)
{
struct timeval tv;
int err;
tv.tv_sec = seconds; //超時時間
tv.tv_usec = 0;
do
{
err = select(0,NULL,NULL,NULL,&tv); //將nfds設置為0即為超時函數
}while(err<0 && errno==EINTR); //
}