天天看點

Linux IO模型漫談(5)- IO複用模型之selectselect函數fd_set集合操作伺服器端代碼:用戶端1 代碼:用戶端2代碼:調用步驟:

首先需要了解的是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 &lt;stdio.h&gt;</code>

<code>#include &lt;sys/types.h&gt;</code>

<code>#include &lt;sys/socket.h&gt;</code>

<code>#include &lt;netinet/in.h&gt;</code>

<code>#include &lt;string.h&gt;</code>

<code>#include &lt;unistd.h&gt;</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>*) &amp;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 *) &amp;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>*) &amp;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 *) &amp;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 &gt; maxfd) {</code>

<code>        </code><code>maxfd = listenfd2;</code>

<code>    </code><code>}</code>

<code>    </code><code>FD_ZERO(&amp;allset);</code>

<code>    </code><code>FD_SET(listenfd1, &amp;allset);</code>

<code>    </code><code>FD_SET(listenfd2, &amp;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>, &amp;rset, NULL, NULL, NULL);</code>

<code>        </code> 

<code>        </code><code>//如果是listenfd1 擷取消息</code>

<code>        </code><code>if</code><code>(FD_ISSET(listenfd1, &amp;rset)) {</code>

<code>            </code><code>clilen = sizeof(cli_addr);</code>

<code>            </code><code>clifd = accept(listenfd1, (struct sockaddr *) &amp;cli_addr, &amp;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, &amp;rset)) {</code>

<code>            </code><code>clifd = accept(listenfd2, (struct sockaddr *) &amp;cli_addr, &amp;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>*)&amp;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 *)  &amp;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 伺服器端表

用戶端啟動:

Linux IO模型漫談(5)- IO複用模型之selectselect函數fd_set集合操作伺服器端代碼:用戶端1 代碼:用戶端2代碼:調用步驟:

服務端表現:

Linux IO模型漫談(5)- IO複用模型之selectselect函數fd_set集合操作伺服器端代碼:用戶端1 代碼:用戶端2代碼:調用步驟:

這裡就是使用select函數對多個socket進行讀監聽

本文轉自軒脈刃部落格園部落格,原文連結:http://www.cnblogs.com/yjf512/archive/2012/06/07/2539755.html,如需轉載請自行聯系原作者

繼續閱讀