select實現I O復用

2021-07-13 09:27:15 字數 4225 閱讀 1207

select:

系統提供select函式來實現多路復用輸入/輸出模型。select系統呼叫是用來讓我們的程式監視多個檔案控制代碼的狀態變化的。程式會停在select這裡等待,直到被監視的檔案控制代碼有乙個或

多個發生了狀態改變。關於檔案控制代碼,其實就是乙個整數,我們最熟悉的控制代碼是0、1、2三

個,0是標準輸入,1是標準輸出,2是標準錯誤輸出。0、1、2是整數表示的對應的file *

結構的表示就是stdin、stdout、stderr。

select函式:

#include #include #include int select(int nfds, fd_set *readfds, fd_set *writefds,

fd_set *exceptfds, struct timeval *timeout);

引數nfds是需要監視的最大的檔案描述符值+1;

rdset,wrset,exset分別對應於需要檢測的可讀檔案描述符的集合,可寫檔案描述符的集合及異常檔案描述符的集合。

struct timeval結構用於描述一段時間長度,如果在這個時間內,需要監視的描述符沒有事件發生則函式返回,返回值為0。

fd_clr(inr fd,fd_set* set);用來清除描述片語set中相關fd 的位

fd_isset(int fd,fd_set *set);用來測試描述片語set中相關fd 的位是否為真

fd_set(int fd,fd_set*set);用來設定描述片語set中相關fd的位

fd_zero(fd_set *set);用來清除描述片語set的全部位

引數timeout為結構timeval,用來設定select()的等待時間,

(1)如果引數timeout設為:

null:則表示select()沒有timeout,select將一直被阻塞,直到某個檔案描述符上發生了

事件。(2)0:僅檢測描述符集合的狀態,然後立即返回,並不等待外部事件的發生。

(3)特定的時間值:如果在指定的時間段裡沒有事件發生,select將超時返回。

函式返回值:

執行成功則返回檔案描述詞狀態已改變的個數

如果返回0代表在描述詞狀態改變前已超過timeout時間,沒有返回;

當有錯誤發生時則返回-1,

select實現i/0復用:

tcp_server.c:

1 #include2 #include3 #include4 #include5 #include6 #include7 #include8 #include9 

10 int fds[64];

11 const int back_log=5;

12 void usage(char* argv)

13 16 int start_up(char* ip,int port)

17 25   struct sockaddr_in local;

26   local.sin_port=htons(port);

27   local.sin_family=af_inet;

28   local.sin_addr.s_addr=inet_addr(ip);

29 30   //bind

31   if(bind(sock,(struct sockaddr*)&local,sizeof(local))<0)

32   

36   //listen

37   if(listen(sock,back_log)<0)

38   

42   return sock;

43 }

44 int main(int argc,char* argv)                         45 

51     int port=atoi(argv[2]);

52     char* ip=argv[1];

53 54 

55     int done=0;

56     int new_sock=-1;

57     int listen_sock=start_up(ip,port);

58     struct sockaddr_in client;

59     socklen_t len=sizeof(client);

60 61     int max_fd;

62     fd_set _reads;

63     fd_set _writes;

64 65     int i=0;

66     int fds_num=sizeof(fds)/sizeof(fds[0]);

67     for(i=0;i0)

83             

89             }

90         }

91         switch(select(max_fd+1,&_reads,&_writes,null,&_timeout))  //_reads,_writes輸入,輸出引數

92         

136                     else if(_s==0)

137                     

140                     else

141                     

144                 }

145                 else

146                 

149                 }

150               }

151         }

152     }

153 return 0;

154 }

tcp_client.c:

2 #include3 #include4 #include5 #include6 #include7 #include8 #include9 #include10 #include11 #include12 

13 14 void usage(char* proc)

15 18 int main(int argc,char* argv)

19 25 char* ip=argv[1];

26 int port=atoi(argv[2]);

27 28     //socket

29     int sock=socket(af_inet,sock_stream,0);

30     if(sock<0)

31     

35     struct sockaddr_in remote;

36     remote.sin_family=af_inet;

37     remote.sin_port=htons(port);

38     remote.sin_addr.s_addr=inet_addr(ip);

39 40      int ret=connect(sock,(struct sockaddr*)&remote,sizeof(remote));

41      if(ret<0)

42      

45 46      char buf[1024];

47      while(1)

48      

56      }

57      return 0;

58 }

結果:

server端:
[admin@www internet1]$ ./tcp_server 127.0.0.1 8080

get connection...4

timeout

we are young

^c

client端:

[admin@www internet1]$ ./tcp_client 127.0.0.1 8080

we are young

^c[admin@www internet1]$

select缺點:

(1)每次呼叫select,都需要把fd集合從使用者態拷貝到核心態,這個開銷在fd很多時會很大

(2)同時每次呼叫select都需要在核心遍歷傳遞進來的所有fd,這個開銷在fd很多時也很大

(3)select支援的檔案描述符數量太小了,預設是1024

I O復用 select 學習

最近在學習網路程式設計,覺得select這塊的知識點確實比較難以理解,在學習socket網路通訊機制時,只是習慣寫諸如connect accept recv或recvfrom這樣的阻塞程式,所謂阻塞方式block,顧名思義,就是程序或是執行緒執行到這些函式時必須等待某個事件的發生,如果事件沒有發生,...

select用於實現I O多路復用

阻塞和非阻塞 阻塞函式在完成其指定的任務以前不允許程式呼叫另乙個函式。例如,程式執行乙個讀資料的函式呼叫時,在此函式完成讀 操作以前將不會執行下一程式語句。當伺服器執行到accept語句時,而沒有客戶連線服務請求到來,伺服器就會停止在accept語句上等待連線服務請求 的到來。這種情況稱為阻塞 bl...

IO多路復用 select

select系統呼叫的目的是 在一段指定時間內,監聽使用者感興趣的檔案描述符上的可讀 可寫和異常事件。poll和select應該被歸類為這樣的系統 呼叫,它們可以阻塞地同時探測一組支援非阻塞的io裝置,直至某乙個裝置觸發了事件或者超過了指定的等待時間 也就是說它們的職責不是做io,而是幫助 呼叫者尋...