select I O多路復用

2021-09-06 05:21:35 字數 2596 閱讀 5325

使用select函式的套接字

如果你想保持現有連線的同時,偵聽新的連線,怎麼辦呢?

普通的做法(使用recv, accept是做不到的)。當使用accetp等待新的連線時,程式是阻塞的,也就沒辦法再同原有連線保持通訊。

另一種做法是,使用非阻塞方式,但這會浪費了寶貴的cpu時間(你的不停的輪詢輪詢)。

有沒有更好的辦法呢?答案是肯定的 – 使用select函式。

select可以幫助你同時監聽多個套接字。它會告訴你哪個套接字讀資料就緒, 哪個套接字寫資料就緒,哪個套接字發生錯誤。

使用select意味著使用i/o多路技術。

select函式標頭檔案:

#include

#include

#include

select函式原型:

int select(int numfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);

詳細資訊可檢視 man select

select()函式的引數說明:

numfds 是readfds,writefds,exceptfds 中fd 集合中檔案描述符中最大的數字加上1。

readfds 中的fd 集合將由select 來監視是否可以讀取。

writefds 中的fds 集合將由select 來監視是否可以寫入。

exceptfds 中的fds 集合將由select 來監視是否有例外發生。

timeout 是用來設定等待超時的

返回值:

如果成功,則返回就緒的檔案描述符的數量。超時一般返回0。錯誤返回-1。

這個timeval 結構定義如下:

struct timeval

;只需要將tv_sec 設定為你想等待的秒數,然後設定tv_usec 為想等待的微秒數(真正

的時間就是tv_sec 所表示的秒數加上tv_usec 所表示的微秒數)。當select()函式返回的時候,timeval 中的時間將會被設定為執行為select()後還剩下的時間。

如果你想知道是是否可以從標準輸入和一些套接字(sockfd)中讀取資料,你就可以把檔案描述符和sockfd 加入readfds 中。numfds 的數值設成readfds 中檔案描述符中最大的那個加上一,也就是sockfd+1(因為標準輸入的檔案描述符的值為0 ,所以其他任何的檔案描述符都會比標準輸入的檔案描述符大)。

當select()函式返回的時候,readfds 將會被修改用來告訴你哪乙個檔案描述符你可以用來讀取資料。使用fd_isset() 巨集,你可以選出select()函式執行的結果。

處理fd_set的巨集:

fd_zero(fd_set *set)將乙個檔案描述符集合清零

fd_set(int fd, fd_set *set)將檔案描述符fd 加入集合set 中 – 這樣select就會去監聽它的狀態。

fd_clr(int fd, fd_set *set)將檔案描述符fd 從集合set 中刪除 – select不再去監聽它的狀態。

fd_isset(int fd, fd_set *set)檢測fd在fdset集合中的狀態是否變化。當檢測到fd狀態傳送變化時返回真,否則,返回假。

下面程式,等待從標準輸入輸入資料,並列印所輸入的資料。如果3秒內沒輸入(輸入回車才算輸入就緒),則列印超時或出錯。

#include #include 

#include

#include

int main(int argc, char **argv)

}else

return0;

}

下面是使用select同時偵聽多個連線的例子:

#include#include

#include

in.h>#include

#include

#define port 1234

#define maxsockfd 10

int main(int argc, char **argv)

bzero(&addr,sizeof

(addr));

addr.sin_family =af_inet;

addr.sin_port =htons(port);

addr.sin_addr.s_addr =htonl(inaddr_any);

if(bind(sockfd,&addr,sizeof(addr))<0

)

if(listen(sockfd,3)<0

)

for(fd=0;fd)

is_connected[fd]=0

;

while(1

)

if(!select(maxsockfd,&readfds,null,null,null))

continue

;

for(fd=0;fd)

else

//已處理的連線有讀就緒

else

//成功讀取資料

printf("%s"

,buffer);}}

}}

}

select io 多路復用

select主要用於檢測多個fd狀態,可檢測fd大小收核心編譯巨集 fd setsize限制,預設為1024。當開啟的fd較多時,select的效率會降低。可修改下面簡單伺服器模型為僅接受連線,當fd數量超過20000時,select返回明顯變慢。void testselectsocket else...

Linux IO多路復用

一.select 函式 include include include int select int n,fd set readfds,fd set writefds,fd set exceptfds,struct timeval timeout fd clr int fd,fd set set f...

I O多路復用

一 五種i o模型 1 阻塞i o模型 最流行的i o模型是阻塞i o模型,預設情形下,所有套介面都是阻塞的。我們以資料報套介面為例來講解此模型 我們使用udp而不是tcp作為例子的原因在於就udp而言,資料準備好讀取的概念比較簡單 要麼整個資料報已經收到,要麼還沒有。然而對於tcp來說,諸如套介面...