首先需要了解的是select函数:
#include<sys/select.h>
#include<sys/time.h>
int select (int maxfd , fd_set *readset ,fd_set *writeset, fd_set *exceptionset , const struct timeval * timeout);
返回:就绪描述字的正数目,0——超时,-1——出错
参数解释:
maxfd: 最大的文件描述符(其值应该为最大的文件描述符字 + 1)
readset: 内核读操作的描述符字集合
writeset:内核写操作的描述符字集合
exceptionset:内核异常操作的描述符字集合
timeout:等待描述符就绪需要多少时间。NULL代表永远等下去,一个固定值代表等待固定时间,0代表根本不等待,检查描述字之后立即返回。
注意:readset,writeset,exceptionset都是值-结果参数,意思就是他们传进入指针进去,函数根据指针可以修改对应的fd_set
fd_set和名字一样,是一个描述符的集合。有下面几个操作:
void FD_ZERO(fd_set *fdset); /* 将所有fd清零 */
void FD_SET(int fd, fd_set *fdset); /* 增加一个fd */
void FD_CLR(int fd, fd_set *fdset); /* 删除一个fd */
int FD_ISSET(int fd, fd_set *fdset); /* 判断一个fd是否有设置 */
我们现在要做一个select使用的server,server监听两个端口(7778和7779)的socket。再使用两个cli,一个client连接到7778端口,另一个client连接到7779端口。
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
<code>#include <stdio.h></code>
<code>#include <sys/types.h></code>
<code>#include <sys/socket.h></code>
<code>#include <netinet/in.h></code>
<code>#include <string.h></code>
<code>#include <unistd.h></code>
<code>int</code> <code>main(</code><code>int</code> <code>argc,</code><code>char</code> <code>*argv[])</code>
<code>{</code>
<code> </code><code>//这个服务器同时监听7777和7778两个端口</code>
<code> </code>
<code> </code><code>//绑定监听7779端口的fd</code>
<code> </code><code>int</code> <code>listenfd1;</code>
<code> </code><code>struct sockaddr_in serv_addr1;</code>
<code> </code><code>listenfd1 = socket(AF_INET, SOCK_STREAM,</code><code>0</code><code>);</code>
<code> </code><code>bzero((</code><code>char</code> <code>*) &serv_addr1, sizeof(serv_addr1));</code>
<code> </code><code>serv_addr1.sin_family = AF_INET;</code>
<code> </code><code>serv_addr1.sin_port = htons(</code><code>7777</code><code>);</code>
<code> </code><code>serv_addr1.sin_addr.s_addr = INADDR_ANY;</code>
<code> </code><code>bind(listenfd1, (struct sockaddr *) &serv_addr1, sizeof(serv_addr1));</code>
<code> </code><code>listen(listenfd1,</code><code>5</code><code>);</code>
<code> </code><code>//绑定监听7778端口的fd</code>
<code> </code><code>int</code> <code>listenfd2;</code>
<code> </code><code>struct sockaddr_in serv_addr2;</code>
<code> </code><code>listenfd2 = socket(AF_INET, SOCK_STREAM,</code><code>0</code><code>);</code>
<code> </code><code>bzero((</code><code>char</code> <code>*) &serv_addr2, sizeof(serv_addr2));</code>
<code> </code><code>serv_addr2.sin_family = AF_INET;</code>
<code> </code><code>serv_addr2.sin_port = htons(</code><code>7778</code><code>);</code>
<code> </code><code>serv_addr2.sin_addr.s_addr = INADDR_ANY;</code>
<code> </code><code>bind(listenfd2, (struct sockaddr *) &serv_addr2, sizeof(serv_addr2));</code>
<code> </code><code>listen(listenfd2,</code><code>5</code><code>);</code>
<code> </code><code>int</code> <code>maxfd;</code>
<code> </code><code>//为什么这里设置两个fd_set?每次select的时候函数会把没有事件发生的描述字清零,所以需要两个集合</code>
<code> </code><code>fd_set allset, rset;</code>
<code> </code><code>maxfd = listenfd1;</code>
<code> </code><code>if</code><code>(listenfd2 > maxfd) {</code>
<code> </code><code>maxfd = listenfd2;</code>
<code> </code><code>}</code>
<code> </code><code>FD_ZERO(&allset);</code>
<code> </code><code>FD_SET(listenfd1, &allset);</code>
<code> </code><code>FD_SET(listenfd2, &allset);</code>
<code> </code><code>int</code> <code>clifd, clilen;</code>
<code> </code><code>struct sockaddr_in cli_addr;</code>
<code> </code><code>char</code> <code>buffer[</code><code>256</code><code>];</code>
<code> </code><code>for</code><code>(;;) {</code>
<code> </code><code>rset = allset;</code>
<code> </code><code>select(maxfd +</code><code>1</code><code>, &rset, NULL, NULL, NULL);</code>
<code> </code>
<code> </code><code>//如果是listenfd1 获取消息</code>
<code> </code><code>if</code><code>(FD_ISSET(listenfd1, &rset)) {</code>
<code> </code><code>clilen = sizeof(cli_addr);</code>
<code> </code><code>clifd = accept(listenfd1, (struct sockaddr *) &cli_addr, &clilen);</code>
<code> </code>
<code> </code><code>bzero(buffer,</code><code>256</code><code>);</code>
<code> </code><code>read(clifd, buffer,</code><code>255</code><code>);</code>
<code> </code><code>printf(</code><code>"Listenfd1 Message is:%s\r\n"</code><code>, buffer);</code>
<code> </code><code>}</code>
<code> </code><code>if</code><code>(FD_ISSET(listenfd2, &rset)) {</code>
<code> </code><code>clifd = accept(listenfd2, (struct sockaddr *) &cli_addr, &clilen);</code>
<code> </code><code>printf(</code><code>"Listenfd2 Message is:%s\r\n"</code><code>, buffer);</code>
<code> </code><code>close(clifd);</code>
<code> </code><code>close(listenfd1);</code>
<code> </code><code>close(listenfd2);</code>
<code> </code><code>return</code> <code>0</code><code>;</code>
<code>}</code>
<code>int</code> <code>main(</code><code>int</code> <code>argc,</code><code>char</code><code>* argv[])</code>
<code> </code><code>int</code> <code>socketfd, n;</code>
<code> </code><code>socketfd = socket(AF_INET, SOCK_STREAM,</code><code>0</code><code>);</code>
<code> </code><code>struct sockaddr_in serv_addr;</code>
<code> </code><code>bzero((</code><code>char</code> <code>*)&serv_addr, sizeof(serv_addr));</code>
<code> </code><code>serv_addr.sin_family = AF_INET;</code>
<code> </code><code>serv_addr.sin_port = htons(</code><code>7778</code><code>);</code>
<code> </code><code>connect(socketfd,(struct sockaddr *) &serv_addr, sizeof(serv_addr));</code>
<code> </code><code>write(socketfd,</code><code>"client message"</code><code>,</code><code>14</code><code>);</code>
<code> </code><code>serv_addr.sin_port = htons(</code><code>7779</code><code>);</code>
1 启动服务器端
2 启动客户端1
3 启动客户端2
4 服务器端表
客户端启动:

服务端表现:
这里就是使用select函数对多个socket进行读监听
本文转自轩脉刃博客园博客,原文链接:http://www.cnblogs.com/yjf512/archive/2012/06/07/2539755.html,如需转载请自行联系原作者