//建立socket
int s = socket(AF_INET, SOCK_STREAM, 0);
//繫結IP地址和埠號port
bind(s, ...)
//監聽使用者端連線
listen(s, ...)
//接受使用者端連線
int c = accept(s, ...)
//接收使用者端資料
recv(c, ...);
//處理資料
operation(...)
建立socket時,作業系統會建立一個由檔案系統管理的socket物件。這個socket物件包含了傳送緩衝區、接收緩衝區、等待佇列等成員。等待佇列指向所有需要等待該socket事件的程序。
新的檔案描述符fd都會插入等待佇列中,等到有資料到來時,等待序列會喚醒一個程序來處理資料。
如何同時監視多個socket的資料?
預先傳入一個socket列表,如果列表中的socket都沒有資料,掛起程序,直到有一個socket收到資料,喚醒程序。
int s = socket(AF_INET, SOCK_STREAM, 0);
bind(s, ...)
listen(s, ...)
int fds[] = ;//存放需要監聽的socket
while(1){
int n = select(..., fds, ...)
for(int i=0; i < fds.count; i++){
if(FD_ISSET(fds[i], ...)){
//fds[i]的資料處理
}
}
}
這裡需要注意的問題是:select檢視是否有資料輸入,需要進行遍歷所有的socket;而在程序喚醒後,程序一臉懵逼,只知道有資料來了,卻不知道是誰的資料,因此需要再次進行一次遍歷,找到資料來自於哪個socket。這種多次遍歷,每次都要將整個fds列表傳遞給核心,開銷很大,因此我們需要改進一下。
epoll模式相比於select模式,最大的改進在於增加了一箇中間環節「就緒列表」,還有就是分離了「socket插入到等待列表」和「阻塞等待事件到來」這兩個過程。
每次呼叫select都需要這兩步操作,然而大多數應用場景中,需要監視的socket相對固定,並不需要每次都修改。epoll將這兩個操作分開,先用epoll_ctl維護等待佇列,再呼叫epoll_wait阻塞程序。
注意:epoll_wait方法不是使用迴圈的方式看是否有就緒時間,而是epoll_wait()一直阻塞直到:fd產生事件 / 被訊號處理常式打斷 / 超時。
int s = socket(AF_INET, SOCK_STREAM, 0);
bind(s, ...)
listen(s, ...)
int epfd = epoll_create(...);
epoll_ctl(epfd, ...); //將所有需要監聽的socket新增到epfd中
while(1){
int n = epoll_wait(...)
for(接收到資料的socket){
//處理
}
}
select低效的另一個原因在於程式不知道哪些socket收到資料,只能一個個遍歷。如果核心維護一個「就緒列表」,參照已就緒資料的socket,就能避免遍歷。
int epoll_create(int size);
在最初的epoll_create()實現中,size引數將呼叫者希望新增到的檔案描述符的數量告知核心。epoll範例。核心使用該資訊作為內部資料結構初始分配空間的提示,事件。 (如果有必要,如果呼叫方的使用超出了大小提示,核心將分配更多空間。)如今,此提示不再必需(核心無需提示即可動態調整所需資料結構的大小),但是大小必須仍大於零,以便當新的epoll應用程式在較舊的核心上執行時,請確保向後相容。
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
向 epfd 對應的核心epoll 範例新增、修改或刪除對 fd 上事件 event 的監聽。op 可以為 EPOLL_CTL_ADD, EPOLL_CTL_MOD, EPOLL_CTL_DEL 分別對應的是新增新的事件,修改檔案描述符上監聽的事件型別,從範例上刪除一個事件。
int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);
當 timeout 為 0 時,epoll_wait 永遠會立即返回。而 timeout 為 -1 時,epoll_wait 會一直阻塞直到任一已註冊的事件變為就緒。當 timeout 為一正整數時,epoll 會阻塞直到計時 timeout 毫秒終了或已註冊的事件變為就緒。因為核心排程延遲,阻塞的時間可能會略微超過 timeout 毫秒。
https://www.cnblogs.com/Hijack-you/p/13057792.html
https://www.agedcat.com/programming_language/cpp/525.html
https://blog.csdn.net/zhoumuyu_yu/article/details/112472419