----------------------------------------------------------------------
#include <sys/select.h>
#include <sys/time.h>
int select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, const struct timeval *timeout);
返回:准备好描述字的正数目,0—超时,-1—出错。
----------------------------------------------------------------------
参数说明:
maxfdp1: 制定要检查的描述符的个数,实际应用中传入最大描述符加1,表明要检查0到最大描述符中间的所有描述符。
readset、writeset、exceptset: 这三个参数都是值-结果参数,传入的是应用程序想让内核检查的套接字集合,传出的是内核检查过的可进行操作的套接字集合。
timeout: 超时设置,NULL表示一直等,直到有一个套接字准备好I/O时才返回,将秒和微秒两个字段都设置为0表示不等待,立即返回。
fd_set: 存放套接字的集合。
有四个操作fd_set的宏,分别是:
void FD_ZERO(fd_set *fdset);
void FD_SET(int fd, fd_set *fdset);
void FD_CLR(int fd, fd_set *fdset);
void FD_ISSET(int fd, fd_set *fdset);
FD_SET设置文件描述符集fdset中对应于文件描述符fd的位(设置为1)
FD_CLR清除文件描述符集fdset中对应于文件描述符fd的位(设置为0)
FD_ZERO清除文件描述符集fdset中的所有位(既把所有位都设置为0)。
使用这3个宏在调用select前设置描述符屏蔽位,在调用select后使用FD_ISSET来检测文件描述符集fdset中对应于文件描述符fd的位是否被设置。
是一个表示时间的结构体:
1 struct timeval 2 { 3 long tv_sec; /* seconds */ 4 long tv_usec; /* microseconds */ 5 };
以下是一个使用select的简单demo,可以处理多个客户端同时跟服务端通信。
  1 #include <stdio.h>
  2 #include <sys/socket.h>
  3 #include <netinet/in.h>
  4 #include <strings.h>
  5 
  6 #define PORT 8080
  7 #define LISTENQ 5
  8 #define MAXLINE 1024
  9 #define IS_ERROR(condition)  10     if(condition)  11     {  12         printf("Error in func[%s] and line[%d]!\n",  13         __PRETTY_FUNCTION__, __LINE__);  14         return 0;  15     }
 16 
 17 int main(int argc, char *argv[])
 18 {
 19     struct sockaddr_in addrSer;
 20     struct sockaddr_in addrCli;
 21     int listenSock;
 22     int connSock;
 23     int clientSock[FD_SETSIZE];
 24 
 25     int maxSock;     //the max fd
 26     int sumSock;     //sum of client sockets - 1
 27     int nCliLen;       //len of addrCli
 28     int nReady;       //the num of ready sockets
 29 
 30     fd_set allset;
 31     fd_set rset;
 32 
 33     char buf[MAXLINE];
 34     int nRet;
 35     int i;
 36 
 37     /*create listen socket*/
 38     listenSock = socket(AF_INET, SOCK_STREAM, 0);
 39     IS_ERROR(listenSock == -1);
 40 
 41     /*bind listen port*/
 42     bzero(&addrSer, sizeof(addrSer));
 43     addrSer.sin_family      = AF_INET;
 44     addrSer.sin_addr.s_addr = htonl(INADDR_ANY);
 45     addrSer.sin_port        = htons(PORT);
 46     nRet = bind(
 47         listenSock,
 48         (struct sockaddr *)&addrSer,
 49         sizeof(struct sockaddr_in)
 50     );
 51     IS_ERROR(nRet == -1);
 52 
 53     /*listen port*/
 54     nRet = listen(listenSock, LISTENQ);
 55     IS_ERROR(nRet == -1);
 56 
 57     /*init*/
 58     maxSock = listenSock;
 59     sumSock = -1;
 60 
 61     /*Init socket array*/
 62     for (i=0; i<FD_SETSIZE; ++i)
 63     {
 64         clientSock[i] = -1;
 65     }
 66 
 67     /*Init fd_set*/
 68     FD_ZERO(&allset);
 69     FD_SET(listenSock, &allset);
 70 
 71     /*request*/
 72     while (1)
 73     {
 74         rset = allset;
 75         nReady = select(maxSock+1, &rset, NULL, NULL, NULL);
 76 
 77         /*accept*/
 78         if (FD_ISSET(listenSock, &rset))
 79         {
 80             nCliLen = sizeof(addrCli);
 81             connSock = accept(listenSock, (struct sockaddr *)&addrCli, &nCliLen);
 82             for (i=0; i<FD_SETSIZE; ++i)
 83             {
 84                 if (clientSock[i] < 0)
 85                 {
 86                     clientSock[i] = connSock;
 87                     break;
 88                 }
 89             }
 90 
 91             if (i == FD_SETSIZE)
 92             {
 93                 printf("too many clients!\n");
 94                 return 0;
 95             }
 96 
 97             FD_SET(connSock, &allset);
 98 
 99             maxSock = (maxSock < connSock) ? connSock : maxSock;
100             sumSock = (sumSock < i) ? i : sumSock;
101 
102             if (--nReady <= 0)
103             {
104                 continue;
105             }
106         }
107 
108         /*send and recv*/
109         for (i=0; i<=sumSock; ++i)
110         {
111             if (clientSock[i] < 0)
112             {
113                 continue;
114             }
115 
116             if (FD_ISSET(clientSock[i], &rset))
117             {
118                 nRet = recv(clientSock[i], buf, MAXLINE, 0);
119 
120                 if (nRet == 0 || nRet == -1)
121                 {
122                     printf("read sock %d err, nRet = %d!\n", clientSock[i], nRet);
123                     close(clientSock[i]);
124                     FD_CLR(clientSock[i], &allset);
125                     clientSock[i] = -1;
126                 }
127                 else if (-1 == send(clientSock[i], buf, nRet, 0))
128                 {
129                     printf("write sock %d err!\n", clientSock[i]);
130                     close(clientSock[i]);
131                     FD_CLR(clientSock[i], &allset);
132                     clientSock[i] = -1;
133                 }
134 
135                 if (--nReady <= 0)
136                 {
137                     break;
138                 }
139             } //if (FD_ISSET(clientSock[i], &rset))
140         } //for (i=0; i<=sumSock; ++i)
141     } //while(1)
142 
143     return 0;
144 }
原文:http://www.cnblogs.com/mhscn/p/4740858.html