1. 阻塞與非阻塞
阻塞方式block,程序執行到這一函式時必須等待事件發生,如果沒發生,就一直阻塞函式不能返回
非阻塞 non-block
程序或執行緒執行不必等待事件發生一旦執行肯定返回以不停返回返回值來反應函式執**況
select就是這樣監視描述符的變化
2.select模型
兩結構體:
structfd_set存放描述符,檔案控制代碼的聚合
建立檔案聯絡四個巨集
fd_zero(fd_set*fd_set);//清空fdset與所有檔案控制代碼的聯絡
fd_set(intfd,fd_set *fdset);//建立檔案控制代碼與fdset的聯絡
fd_clr(intfd,fd_set *fdset); 清除檔案控制代碼fd與fdset的聯絡
fd_isset(intfd,fd_set*fdset);//檢查fdset聯絡的檔案控制代碼fd是否讀寫,>0表示可讀寫
structtimeval 兩個成員 tv_sec表示秒數,tv_usec表示毫秒數
select函式原型
int select(intnfds,fd_set *rdfds,fd_set *wtfds,fd_set *exfds,struct timeval *timeout);
a.其中rdfds(wtfds)讀集,度過有乙個檔案可讀,select返回乙個大於
0的值表示檔案可讀超出timeout時間select返回0,發生錯誤返回負值,
可傳入null
表示不關心檔案讀寫變化
exfds異常檔案集有特殊情況發生select返回
b.timeval*out 若果設定為null
變為阻塞方式
設定為0完全非阻塞
c.返回值大於0檔案可讀或可寫
返回值為0,out of time
返回值小於0,select錯誤
network.h
#include #include #include #include #include #include #include #include #include #include #define err_exit(m) \
do while(0)
ssize_t readn(int fd, void *usrbuf, size_t n);
ssize_t writen(int fd, void *usrbuf, size_t n);
ssize_t recv_peek(int sockfd, void *usrbuf, size_t n);
ssize_t readline(int sockfd, void *usrbuf, size_t maxline);
network.c
#include "network.h"
ssize_t readn(int fd, void *usrbuf, size_t n)
else if(nread == 0) // eof
break;
nleft -= nread;
bufp += nread;
}return (n - nleft);
}ssize_t writen(int fd, void *usrbuf, size_t n)
nleft -= nwrite;
bufp += nwrite;
}return n; //這裡不是 n- nleft 必須是n
}//recv_peek選項完成一次正確的讀取過程。
ssize_t recv_peek(int sockfd, void *buf, size_t len)
if (nread < 0)
break;
}return nread;
}ssize_t readline(int sockfd, void *buf, size_t maxline)
nread = ret;
int i;
for (i = 0; i < nread; ++i)
total += ret;
ptr += ret;
*ptr = 0;
return total; //返回此行的長度 '\n'包含在其中}}
//如果沒有發現\n,這些資料應全部接收
ret = readn(sockfd, ptr, nread);
if (ret != nread)
nleft -= nread;
total += nread;
ptr += nread;
}*ptr = 0;
return maxline-1;
}
client.c#include "network.h"
#include #include void do_service(int peerfd)
; char sendbuf[1024]=;
//init
fd_set readset;
fd_zero(&readset);
//防止重定向不用stdin_fileno
int stdin_fd=fileno(stdin);
int maxfd=(stdin_fd>peerfd)?stdin_fd:peerfd;
int nready;
while(1)
if(fd_isset(stdin_fd,&readset))
if(fd_isset(peerfd,&readset))
else
if(ret==0)
printf("recv data : %s",recvbuf);}}
}int main(int argc, const char *argv)
1.使用select編寫客戶端程式的一般步驟:
初始化引數,包括readset、maxfd、nready
while(1)
1.先重新設定readset
2.執行select呼叫,包括檢查返回值
3.依次檢查stdin和peerfd,如果是前者就從鍵盤讀取資料,如果是後者,就使用readline接收網路資料。
3.poll模型
client.c
#include "network.h"
#include void do_service(int peerfd)
; char sendbuf[1024]=;
//init
struct pollfd client[2];//listen 2 fd
client[0].fd=fileno(stdin);
client[0].events =pollin; //listen read events
client[1].fd=peerfd;
client[1].events=pollin;
int maxi =1; //max subscript of array client[1]
int nready;// join poll echo value
while(1)
else if(nready ==0)
//check stdin and peerfd according to priority
if(client[0].revents & pollin)
else
}if(client[1].revents&pollin)
printf("recv data: %s",recvbuf);}}
}int main(int argc, const char *argv)
使用poll編寫客戶端的一般步驟:
準備陣列(這裡為2),填入相應的fd以及events。還有maxi、nready
while(1)
1.執行poll,以及檢查返回值
2.檢查兩個fd,通過revents欄位
IO多路復用 select
select系統呼叫的目的是 在一段指定時間內,監聽使用者感興趣的檔案描述符上的可讀 可寫和異常事件。poll和select應該被歸類為這樣的系統 呼叫,它們可以阻塞地同時探測一組支援非阻塞的io裝置,直至某乙個裝置觸發了事件或者超過了指定的等待時間 也就是說它們的職責不是做io,而是幫助 呼叫者尋...
IO多路復用 select
出自朱有鵬老師的課堂 include include include include include include include include include int main void 當前有兩個fd,乙個是fd乙個是0 處理 myset fd zero myset 全部清零 fd set ...
I O多路復用 select
int select int n,fd set readfds,fd set writefds,fd set exceptfds,struct timeval timeout 有三種型別的描述符型別 readset writeset exceptset,分別對應讀 寫 異常條件的描述符集合。fd s...