多路i/o復用表示支援多個任務同時對某一程序的i/o程序操作,普通的read/write只能實現同一時間操作乙個,無法實現網路通訊的併發操作。那麼多路復用i/o分為三種機制:select/poll/epoll
1.占用記憶體多 2.程序(執行緒)切換時間多。3.程序(執行緒)之間同步麻煩
在主控執行緒中將需要監控的檔案描述符儲存到檔案描述符集中,該檔案描述符集為乙個位圖,我們知道檔案描述符正常情況下總是累加上去的,也是乙個整數,因此這個整數巧好可以表示該檔案描述符在位圖的位置(例如點陣圖上的3號位置為1,表示檔案描述符等於3有事件發生,否則為空閒。),將伺服器和客戶端的檔案描述符加入到該(檔案描述符集)點陣圖中進行監控,若有事件發生則才處理。
nfds: 監控的檔案描述符集裡最大檔案描述符加1,因為此引數會告訴核心檢測前多少個檔案描述符的狀態
readfds:監控有讀資料到達檔案描述符集合,傳入傳出引數
writefds:監控寫資料到達檔案描述符集合,傳入傳出引數
exceptfds:監控異常發生達檔案描述符集合,如帶外資料到達異常,傳入傳出引數
timeout:定時阻塞監控時間,3種情況
1.null,永遠等下去
2.設定 timeval,等待固定時間
3.設定 timeval裡時間均為0,檢查描述字後立即返回,輪詢
struct timeval ;
void fd_clr(int fd, fd_set *set); 把檔案描述符集合裡fd清0
int fd_isset(int fd, fd_set *set); 測試檔案描述符集合裡fd是否置1
void fd_set(int fd, fd_set *set); 把檔案描述符集合裡fd位置1
void fd_zero(fd_set *set); 把檔案描述符集合裡所有位清0
函式2-5均為巨集定義函式
通過上述api可知道:
select監控的有三種事件的檔案描述符集(讀、寫、異常)。以及可設定阻塞時間,大大地解決死等的弊端,select無請求後,主控函式將執行後續指令。
select監聽的檔案描述符集最大支援1024,大小可用巨集定義表示fd_setsize( = 1024),解決1024以下客戶端時使用select是很合適的,後面會講解poll,解決1024的限制。
select採用的是輪詢模型,數量級在千級還是很適合,但是如果更大會導致每次監控都要從檔案描述符集從0到maxfd+1進行遍歷,會大大降低伺服器響應效率,不應在select上投入更多精力
這是客戶端
/*./client serv_ip serv_port */
#include
"net.h"
void usage (
char
*s)int main (
int argc,
char
**ar**)
/* 1. 建立socket fd */if(
(fd = socket (af_inet, sock_stream,0)
)<0)
port = atoi (ar**[2]
);if(port <
5000
)/*2.連線伺服器 */
/*2.1 填充struct sockaddr_in結構體變數 */
bzero (
&sin,
sizeof
(sin));
sin.sin_family = af_inet;
sin.sin_port = htons (port)
;//網路位元組序的埠號
#if 0
sin.sin_addr.s_addr = inet_addr (serv_ip_addr)
;#else
if(inet_pton (af_inet, ar**[1]
,(void*)
&sin.sin_addr)!=1
)#endif
if(connect (fd,
(struct sockaddr *
)&sin,
sizeof
(sin)
)<0)
printf (
"client staring...ok!\n");
int ret =-1
; fd_set rset;
int maxfd =-1
;struct timeval tout;
char buf[bufsiz]
;while(1
)while
(ret <
0&& eintr == errno);if
(ret <0)
if(!ret)
continue
;//伺服器關閉
if(write (fd, buf, strlen (buf)
)<0)
if(!strncasecmp (buf, quit_str, strlen (quit_str)))
}if(fd_isset (fd,
&rset)
)while
(ret <
0&& eintr == errno);if
(ret <0)
if(!ret)
break
;/* 伺服器關閉 */
//there is a bug,fixme!!
printf (
"server said: %s\n"
, buf);if
((strlen
(buf)
>
strlen
(serv_resp_str))&&
!strncasecmp (buf+
strlen
(serv_resp_str)
, quit_str, strlen (quit_str)))
}}/*4.關閉套接字 */
close (fd)
;}
參考: IO多路復用模型之Select
在unix c中,socket相關的函式操作都是阻塞式的,在單執行緒下服務端只能處理乙個客戶端請求。採用多執行緒處理客戶端請求,雖然能充分發揮多核cpu能力,但是在客戶端連線過多,併發度維持相對較高水平時,多執行緒引起執行緒的上下文切換將導致系統效率低下。select多路復用模型的核心思想,在單執行...
IO多路復用 select模型
客戶端 見 c s通訊 伺服器阻塞型使用 伺服器端 include include include include include include include include include include include include int main set local address m...
IO多路復用 select
select系統呼叫的目的是 在一段指定時間內,監聽使用者感興趣的檔案描述符上的可讀 可寫和異常事件。poll和select應該被歸類為這樣的系統 呼叫,它們可以阻塞地同時探測一組支援非阻塞的io裝置,直至某乙個裝置觸發了事件或者超過了指定的等待時間 也就是說它們的職責不是做io,而是幫助 呼叫者尋...