多路復用IO模型之select

2021-10-03 23:44:32 字數 3126 閱讀 7868

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