系統提供select函式來實現多路轉接。
呼叫select函式介面的特點:一次需要等待多個檔案描述符。
select函式原型:
#include #include #include int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
nfds:要關心的最大檔案描述符+1,限定了檔案描述符的遍歷區間。
乙個檔案描述符需要關心三個事件:
讀事件寫事件
異常事件
fd_set實際上是乙個位圖
timeval結構體
timeout:表示select可以每隔多久時間醒過來等待一次,如果所期望的時間沒有發生,就去忙別的。
使用select編寫簡單的伺服器:
#include#include#include#include#include#include#include#include#define max_fd sizeof(fd_set)*8//最多可監聽多少個檔案描述符
#define init -1
int starup(int port)
int opt=1;
setsockopt(sock,sol_socket,so_reuseaddr,&opt,sizeof(opt));
struct sockaddr_in local;
local.sin_family=af_inet;
local.sin_port=htons(port);
local.sin_addr.s_addr=htonl(inaddr_any);
if(bind(sock,(struct sockaddr*)&local,sizeof(local))<0)
if(listen(sock,5)<0)
return sock;
}void array_init(int* fd_array,int num)
}void service(int* fd_array,int num,fd_set* rfds)
if(array_add(fd_array,num,new_sock)<0)
}else;
ssize_t s=read(fd,buf,sizeof(buf)-1);
if(s>0)else if (s==0)else}}
}}int main(int argc,char* argv)
//建立監聽套接字
int listen_sock=starup(atoi(argv[1]));
int fd_array[max_fd];
//初始化陣列
array_init(fd_array,max_fd);
//將監聽到的新連線加入到陣列裡
array_add(fd_array,max_fd,listen_sock);
fd_set rfds;//位圖
int max_fd=0;
for(;;);
//清空位圖
fd_zero(&rfds);
//將陣列中的檔案描述符新增到位圖中
max_fd=set_rfds(fd_array,max_fd,&rfds);
switch(select(max_fd+1,&rfds,null,null,&timeout))
}}
select缺點:
每次呼叫select,都要手動設定fd集合。
select限定了可接收的檔案描述符上限。
I O多路轉接之select
什麼是i o多路轉接技術 先構建一張有關描述符的列表,然後呼叫乙個函式,直到這些描述符中的乙個已準備好進行i o時,該函式才返回,在返回時,他告訴程序哪些描述符已準備好可以進行i o。上述呼叫的函式,有select,poll,pselect及poll的增強版epoll等,本文主要介紹select。函...
I O多路轉接之select
下面的巨集提供了處理fd set的這三種描述集的方式 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 用來...
IO多路轉接之select
阻塞io,在核心將資料準備好之前,系統會一直在等待,所有的套接字,預設都是阻塞方式 非阻塞io 如果核心還沒有將資料準備好,系統會呼叫仍然直接返回,並且返回ewouldblock錯誤碼,非阻塞io需要程式設計師迴圈的方式反覆嘗試讀寫檔案描述符,看資料是否準備好,這個過程稱為輪詢,這對cpu來說是很大...