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:
1
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,而是幫助 呼叫者尋...