要想實現乙個簡單的web伺服器模型,一般有以下幾種方法:
1. 多程序(主程序監聽,有新的連線就fork乙個子程序建立連線)
2. 多執行緒(主線程監聽,有新的連線就新建乙個子執行緒建立連線)
3. 使用系統函式select去監聽,當有檔案描述符就緒對其進行處理
4. 使用系統函式poll去監聽,當有檔案描述符就緒對其進行處理
5. 使用系統函式epoll去監聽,當有檔案描述符就緒對其進行處理
3,4,5都是單執行緒,基本原理就是有乙個執行緒在監聽是否有新的客戶端請求,如果有的話就在此客戶端和伺服器之間建立乙個連線。如果客戶端傳來有效資料之後該連線的檔案描述符就處於就緒狀態(在linux系統裡一切都是以檔案的形式存在,所以可以直接通過資源的檔案描述符去作業系統資源),然後伺服器會按順序對就緒狀態的檔案進行處理。這就是i/o多路復用的本質。
因為對於乙個tcp請求,耗時主要在網路傳輸,屬於i/o密集型,cpu處理單個請求一般很快,所以這裡採用單執行緒處理,沒有程序或者執行緒之間切換的開銷,也避免了阻塞在無效的連線上(如有些客戶端建立了連線但並沒有傳有效資料或請求,這種連線就沒有必要占用過多系統資源去處理),因此在大多數情況下速度會快。
select是多路復用的第乙個系統函式,他預設最多監聽1024個檔案描述符。後面我會再寫部落格介紹poll以及epoll。
下面是乙個server的實現**以及詳細的注釋,client給server傳小寫字母,server轉化為大寫字母並傳回。
/*
使用select構建乙個簡單的server,實現i/o多路復用。select是單執行緒。
*/#include #include #include #include #include #include #include #define maxline 4096
#define serv_port 8000
int main(int argc, char *ar**)
// 將監聽集置0
fd_zero(&allset);
// 將listenfd放入監聽集
fd_set(listenfd, &allset);
printf("wait connecting...\n");
for (; ;)
// 新的連線
if (fd_isset(listenfd, &rset))
}if (i == fd_setsize)
// 將connfd放入監聽集合
fd_set(connfd, &allset);
// 更新最大檔案描述符
if (connfd > maxfd) maxfd = connfd;
// 更新最大存放有效資料下標
if (i > maxi) maxi = i;
// 如果只建立了乙個新的連線,並沒有被監聽的其他檔案描述符處於就緒狀態,意味著沒有資料需要處理,那麼繼續回到之前select阻塞狀態,等待就緒再進行處理
if (--nready == 0) continue;
}for (i = 0; i <= maxi; i++)
// 業務邏輯,從緩衝區讀入並且轉成大寫,寫入檔案描述符
else
write(sockfd, buf, n);
}if (--nready == 0) break;}}
}close(listenfd);
return 0;
}
將上面**命名為server.c,使用
gcc -o server.o server.c
./server.o
就啟動了伺服器。
這裡我沒有放client端**,不過可以使用系統命令:
nc localhost 8000
去模擬乙個客戶端請求(我伺服器端口設定的8000,可以進行更改)。這樣客戶端伺服器就可以進行通訊了。
select IO復用機制
注 select 原理圖,摘自ibm iseries 資訊中心。返回值返回對應位仍然為1的fd的總數。引數 1.2.1 清空描述符集合fd zero fd set 1.2.2 向描述符集合新增指定描述符fd set int,fd set 1.2.3 從描述符集合刪除指定描述符fd clr int,f...
select io 多路復用
select主要用於檢測多個fd狀態,可檢測fd大小收核心編譯巨集 fd setsize限制,預設為1024。當開啟的fd較多時,select的效率會降低。可修改下面簡單伺服器模型為僅接受連線,當fd數量超過20000時,select返回明顯變慢。void testselectsocket else...
select I O多路復用
使用select函式的套接字 如果你想保持現有連線的同時,偵聽新的連線,怎麼辦呢?普通的做法 使用recv,accept是做不到的 當使用accetp等待新的連線時,程式是阻塞的,也就沒辦法再同原有連線保持通訊。另一種做法是,使用非阻塞方式,但這會浪費了寶貴的cpu時間 你的不停的輪詢輪詢 有沒有更...