select()函数

  select(),确定一个或多个套接口的状态,本函数用于确定一个或多个套接口的状态,对每一个套接口,调用者可查询它的可读性、可写性及错误状态信息,用fd_set结构来表示一组等待检查的套接口,在调用返回时,这个结构存有满足一定条件的套接口组的子集,并且select()返回满足条件的套接口的数目。有一组宏可用于对fd_set的操作,这些宏与Berkeley Unix软件中的兼容,但内部的表达是完全不同的。

简述

确定一个或多个套接口的状态,如需要则等待。

#include <sys/select.h>

int select( int nfds, fd_set FAR* readfds, fd_set * writefds, fd_set * exceptfds, const struct timeval * timeout);

nfds:是一个整数值,是指集合中所有文件描述符的范围,即所有文件描述符的最大值加1,不能错!在Windows中这个参数的值无所谓,可以设置不正确。

readfds:(可选)指针,指向一组等待可读性检查的套接口。

writefds:(可选)指针,指向一组等待可写性检查的套接口。

exceptfds:(可选)指针,指向一组等待错误检查的套接口。

timeout:select()最多等待时间,对阻塞操作则为NULL。

注释

readfds参数标识等待可读性检查的套接口。如果该套接口正处于监听listen()状态,则若有连接请求到达,该套接口便被标识为可读,这样一个accept()调用保证可以无阻塞完成,对其他套接口而言,可读性意味着有排队数据供读取。或者对于SOCK_STREAM类型套接口来说,相对于该套接口的虚套接口已关闭,于是recv()recvfrom()操作均能无阻塞完成,writefds参数标识等待可写性检查的套接口。如果一个套接口正在connect()连接(非阻塞),可写性意味着连接顺利建立。如果套接口并未处于connect()调用中,可写性意味着send()sendto()调用将无阻塞完成。〔但并未指出这个保证在多长时间内有效,特别是在多线程环境中〕。

exceptfds参数标识等待带外数据存在性或意味错误条件检查的套接口,请注意如果设置了SO_OOBINLINE选项为假FALSE,则只能用这种方法来检查带外数据的存在与否,对于SO_STREAM类型套接口,远端造成的连接中止和KEEPALIVE错误都将被作为意味出错。如果套接口正在进行连接connect()(非阻塞方式),则连接试图的失败将会表现在exceptfds参数中。

如果对readfds、writefds或exceptfds中任一个组类不感兴趣,可将它置为空NULL。

在socket.h头文件中共定义了四个宏来操作描述字集。FD_SETSIZE变量用于确定一个集合中最多有多少描述字(FD_SETSIZE缺省值为64,可在包含socket.h前用#define FD_SETSIZE来改变该值)。对于内部表示,fd_set被表示成一个套接口的队列,最后一个有效元素的后续元素为INVAL_SOCKET。宏为:FD_CLR(s,*set):从集合set中删除描述字s。FD_ISSET(s,*set):若s为集合中一员,非零;否则为零。FD_SET(s,*set):向集合添加描述字s。FD_ZERO(*set):将set初始化为空集NULL。

timeout参数控制select完成的时间。若timeout参数为空指针,则select将一直阻塞到有一个描述字满足条件,否则的话,timeout指向一个timeval结构,其中指定了select调用在返回前等待多长时间。如果timeval为{0,0},则select立即返回,这可用于探询所选套接口的状态,如果处于这种状态,则select调用可认为是非阻塞的,且一切适用于非阻塞调用的假设都适用于它,举例来说,阻塞钩子函数不应被调用,且套接口实现不应yield。

返回值

select()调用返回处于就绪状态并且已经包含在fd_set结构中的描述字总数;如果超时则返回0;否则的话,返回SOCKET_ERROR错误,应用程序可通过WSAGetLastError获取相应错误代码。

当返回为-1时,所有描述符集清0。

当返回为0时,表示超时。

当返回为正数时,表示已经准备好的描述符数。

select()返回后,在3个描述符集里,依旧是1的位就是准备好的描述符。这也就是为什么,每次用select后都要用FD_ISSET的原因。

错误代码

WSANOTINITIALISED:在使用此API之前应首先成功地调用WSAStartup()。

WSAENETDOWN:套接口实现检测到网络子系统失效。

WSAEINVAL:超时时间值非法,

WSAEINTR:通过一个WSACancelBlockingCall()来取消一个阻塞的

WSAEINPROGRESS:一个阻塞的套接口调用正在运行中。

WSAENOTSOCK:描述字集合中包含有非套接口的元素。

调用


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

//下面是示例代码:

//代码是服务器TCP模型,采用多路复用的select函数实现了循环的监听并接受客户端的功能,其中也包含了上传下载的功能*/

#include<stdio.h>

#include<stdlib.h>

#include<unistd.h>

#include<sys/socket.h>

#include<string.h>

#include<netinet/in.h>

#include<sys/ioctl.h>

#include<sys/stat.h>

#include<fcntl.h>

#include<sys/types.h>

#include<dirent.h>

int main()

{

    struct sockaddr_in seraddr,cliaddr;

    int listenfd,connfd,fd1,fd2,n,m,l,port;

    char user[20],buf[4096];

    fd_set  readfds,tmpfds;//岗哨监控集合

    socklen_t addrlen;

    DIR *dr;

    struct dirent *file;

    printf("请输入需要设定的服务器名称:");

    scanf("%s",user);

    

    printf("请输入需要设定的服务器端口:");

    scanf("%d",&port);

    getchar();

    if((listenfd=socket(AF_INET,SOCK_STREAM,0))<0)

    {

        perror("创建失败");

       exit(-1);

    }

    

    

    /*开始设定服务器的参数地址类型,IP,PORT*/

    memset(&seraddr,0,sizeof(seraddr));//将服务器的初值空间清空,防止转化过程有影响

    seraddr.sin_family=AF_INET;

    seraddr.sin_port=htons(port);//将得到的本地端口转换为网络字节序

    seraddr.sin_addr.s_addr=htonl(INADDR_ANY);//将得到的ip地址字符串转换为网络字节序的ip地址数值

    if((bind(listenfd,(struct sockaddr*)&seraddr,sizeof(seraddr))<0))

    {

        perror("绑定失败");

       exit(-1);

    }

    printf("绑定创建\n");

    if((connfd=listen(listenfd,50))<0)

    {

        perror("监听失败");

        exit(-1);

    }

    printf("开始监听\n");

    FD_ZERO(&readfds);//初始化文件集

    FD_SET(listenfd,&readfds);//将需要监视的listenfd放入readfds集中

    while(1)//循环监听

    {

        int nread,n;

        tmpfds=readfds;//将监视集传递给临时的监视集中,防止后续的操作修改了监视集

        if(select(FD_SETSIZE,&tmpfds,NULL,NULL,NULL)<0)//设置监视,监视tmpfds内的子fd变化,发生变化的将会被保留在tmpfds中

          {

           perror("监视未成功");

            exit(-1);

         }

        

         for(fd1=0;fd1<FD_SETSIZE;fd1++)//循环找在最大范围内的fd1

        {

           if(FD_ISSET(fd1,&tmpfds))//查找是否fd在tmpfds里面

            {

              if(fd1==listenfd)//判定fd等于监听fd,即监听fd在监视过程中出现变化被发现

              {

                  addrlen=sizeof(cliaddr);

                 connfd=accept(listenfd,(struct sockaddr*)&cliaddr,&addrlen);//开始接收客户

                 FD_SET(connfd,&readfds);//将connfd加入监视集,监视接入的变化

                 printf("接入新的连接\n");

              }

              else

                  {

                      ioctl(fd1,FIONREAD,&nread);//测试在fd中还有nread个字符需要读取

                      if(nread==0)//如果需要读取的数据为0,则关闭检测出来的fd1,并且从监视中移除

                    {

                     close(fd1);

                     FD_CLR(fd1,&readfds);

                      printf("移除\n");

                    }

                      else//如果可读数据不为0,则读出来

                    {

                        int i;

                        char *p=NULL,*q=NULL;

                      n=read(fd1,buf,nread);

                      buf[n]=0;

                      p=buf;

                      

                      

                          if((strncmp(p,"-get",4)==0))

                          {  

                             q=p+5;

                             printf("客户下载文件>%s",q);

                             if((fd2=open(q,O_RDONLY))<0)

                                 perror("打开文件错误");

                            

                             while((m=read(fd2,buf,4096))>0)

                             {

                                 write(connfd,buf,m);

                                 

                             }

                             bzero(buf,sizeof(buf));

                             close(fd1);

                             close(fd2);

                             FD_CLR(fd1,&readfds);

                          

                          }

                          

                          if((strncmp(p,"-up",3)==0))

                          {  

                             q=p+4;

                             printf("客户上传文件%s\n",buf+4);

                             if((fd2=open(q,O_CREAT | O_WRONLY | O_APPEND ,0666))<0)

                             {

                                perror("打开文件写入失败");

                                 

                             }

                             

                             while((m=read(connfd,buf,128))>0)

                             

                                 printf("%s",buf);

                                 write(fd2,buf,m);

                             }

                             bzero(buf,sizeof(buf));

                             close(fd1);

                             close(fd2);

                             FD_CLR(fd1,&readfds);

                          

                          }

                          

                          if((strncmp(p,"-ls",3)==0))

                          {  

                             q=p+4;

                             printf("客户查看文件……");

                             if((dr=opendir(q))==NULL)

                                 perror("打开目录失败");

                             while((file=readdir(dr))!=NULL)

                             {

                                   printf("%s    ",file->d_name);

                                  write(connfd,file->d_name,sizeof(file->d_name));

                             }

                             close(fd1);

                             close(connfd);

                             closedir(dr);

                             FD_CLR(fd1,&readfds);

                          

                          }

                      

                      printf("从客户收取的信息:%s\n",buf);

                    }

                  }

            }//end if 0

            

         

        }//end for 0

    

    }//end while0

    exit(0);

}//end main

相关参考

WSAAsyncSelect(),accept(),connect(), recv(), recvfrom(),send()。

事件用法

概述

触发每一个匹配元素的select事件

这个函数会调用执行绑定到select事件的所有函数,包括浏览器的默认行为。可以通过在某个绑定的函数中返回false来防止触发浏览器的默认行为。

返回值

jQuery

示例

触发所有input元素的select事件:

jQuery 代码:

$("input").select();

时间: 2024-10-11 00:34:44

select()函数的相关文章

select 函数1

Select在Socket编程中还是比较重要的,可是对于初学Socket的人来说都不太爱用Select写程序,他们只是习惯写诸如connect.accept.recv或recvfrom这样的阻塞程序(所谓阻塞方式block,顾名思义,就是进程或是线程执行到这些函数时必须等待某个事件的发生,如果事件没有发生,进程或线程就被阻塞,函数不能立即返回).可是使用Select就可以完成非阻塞(所谓非阻塞方式non-block,就是进程或线程执行此函数时不必非要等待事件的发生,一旦执行肯定返回,以返回值的不

linux下select函数详解及实例

一.概述: 系统提供select函数来实现I/O复用输入/输出模型.select系统调用是用来让我们的程序监视多个文件句柄的状态变化的.程序会停在select这里等待,直到被监视的文件句柄中有一个或多个发生生了状态改变. 二.select函数: 以下为man文本中的解释:  /* According to POSIX.1-2001 */        #include <sys/select.h>        /* According to earlier standards */     

IO复用与select函数

socket select函数的详细讲解 select函数详细用法解析      http://blog.chinaunix.net/uid-21411227-id-1826874.html

select函数详解(转)

Select函数在Socket编程中还是比较重要的,可是对于初学Socket的人来说都不太爱用Select写程序,他们只是习惯写诸如connect. accept.recv或recvfrom这样的阻塞程序(所谓阻塞方式block,顾名思义,就是进程或是线程执行到这些函数时必须等待某个事件的发生,如果事件没有发生,进程或线程就被阻塞,函数不能立即返回).可是使用Select就可以完成非阻塞(所谓非阻塞方式non-block,就是进程或线程执行此函数时不必非要等待事件的发生,一旦执行肯定返回,以返回

linux select函数详解

在Linux中,我们可以使用select函数实现I/O端口的复用,传递给 select函数的参数会告诉内核: •我们所关心的文件描述符 •对每个描述符,我们所关心的状态.(我们是要想从一个文件描述符中读或者写,还是关注一个描述符中是否出现异常) •我们要等待多长时间.(我们可以等待无限长的时间,等待固定的一段时间,或者根本就不等待) 从 select函数返回后,内核告诉我们一下信息: •对我们的要求已经做好准备的描述符的个数 •对于三种条件哪些描述符已经做好准备.(读,写,异常) 有了这些返回信

select()函数以及FD_ZERO、FD_SET、FD_CLR、FD_ISSET

http://hi.baidu.com/%B1%D5%C4%BF%B3%C9%B7%F0/blog/item/e7284ef16bcec3c70a46e05e.html select函数用于在非阻塞中,当一个套接字或一组套接字有信号时通知你,系统提供select函数来实现多路复用输入/输出模型,原型: [cpp] view plain copy #include <sys/time.h> #include <unistd.h> int select(int maxfd,fd_set

socket通信中select函数的使用和解释

select函数的作用: select()在SOCKET编程中还是比较重要的,可是对于初学SOCKET的人来说都不太爱用select()写程序,他们只是习惯写诸如 conncet().accept().recv()或recvfrom这样的阻塞程序(所谓阻塞方式block,顾名思义,就是进程或是线程执行到这些函数时必须等待某个事件发生,如果事件没有发生,进程或线程就被阻塞,函数不能立即返回).可是使用select()就可以完成非阻塞(所谓非阻塞方式non-block,就是进程或线程执行此函数时不必

利用select 函数 实现sleep功能 达到纳米级

利用select 函数 实现sleep达到纳米级 . 当然这个数据计算出来不准确,本身就包含程序执行本身消耗的数量. 原理是把select read write except  fd_set 全部设为NULL,这样select 就可以等待指定的时间. #include <sys/select.h> #include <stdio.h> #include <time.h> #include <sys/time.h> int  main(){         s

转:select()函数以及FD_ZERO、FD_SET、FD_CLR、FD_ISSET

select函数用于在非阻塞中,当一个套接字或一组套接字有信号时通知你,系统提供select函数来实现多路复用输入/输出模型,原型:int select(int maxfd,fd_set *rdset,fd_set *wrset,fd_set *exset,struct timeval *timeout); 所在的头文件为:#include <sys/time.h> 和#include <unistd.h> 先对函数中的参数做一个简单的介绍.参数maxfd是需要监视的最大的文件描述

select函数的用法

首先介绍阻塞方式与非阻塞方式: 阻塞方式(block),就是进程或是线程执行到这些函数时必须等待某个事件的发生.如果事件没有发生,进程或线程就被阻塞,函数不能立即返回. 非阻塞方式(non-block),就是进程或线程执行函数时不必非要等待事件发生,一旦执行必定返回,以返回值的不同来反映函数的执行情况.如果事件发生,则与阻塞方式相同:如果事件没有发生,则返回一个代码告知事件未发生,而进程或线程继续执行.因而效率较高. select函数可以监视我们需要监视的文件描述符的变化情况. 下面介绍两个机构