使用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下面是使用select同時偵聽多個連線的例子:#include
#include
int main(int argc, char **argv)
}else
return0;
}
#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來說,諸如套介面...