标签:
----------------------------------------------------------------------
#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