用多路復用i/o模型實現支援多個客戶端的通訊服務
整理:ackarlix
引言多路復用i/o模型是unix/linux用得的最多的一種i/o模型。這種i/o模型在技術上的實現是包括select()以及fd_***的幾個巨集及常量。在單個程序中支援的客戶端數量由fd_setsize決定。solaris 10和linux 9.0預設為1024個,windows 2000是64個。本文用**給出該i/o模型處理多client的一種實現。
用select開發乙個通訊伺服器
這個伺服器包括接收模組、傳送模組和套介面管理模組。我們只演示與select實現有關的部分,即接收模組和套介面管理模組。下面伺服器類關係圖:
tcp_listen是tcp實現監聽功能,tcp_comm實現tcp的傳送和接收,下在我們重點在於recv和sock_list這兩個類。sock_list定義如下:
class sock_list
public:
// 功能:將乙個值插入到list的尾部
// 引數:要插入的tcp_comm物件
void insert(tcp_comm* t);
// 功能:刪除乙個指定的元素
// 引數:指向要刪除的tcp_comm物件的指標
void remove(tcp_comm* t);
// 功能:從佇列取得所有的元素
// 引數:存放指向tcp_comm物件指標的向量
void get_all(std::vector
& vec);
private:
std::list
_sock_list;
sock_list實現tcp_comm物件的管理。下面我們來看recv類的定義:
class recv
public:
// 功能: 啟動通訊服務
bool start();
private:
// 功能: 接收核心函式,通過多路復用支援多個客戶端
// 返回值: 正常, 0; 失敗,-1
int do_select();
// 初始化套介面集合
void init_readfds(const vector
& vec, fd_set* set);
private:
sock_list* _list;
tcp_listen* _listen; // 監聽套介面
start()是給外部呼叫的:建立監聽套介面物件;監聽;執行do_select()。init_readfds將監聽套介面物件和socket_list中的通訊套介面物件加入到套介面讀套介面集合中。do_select()比較重要,流程:
用init_readfds初始化讀套介面集合;
執行select(),返回進行到下一步;
先檢測監聽套介面是否有連線到來,並將新的連線加入到sock_list中;
再檢測sock_list中的套介面是否有資料可接收。
實現**:
int recv::do_select()
fd_set readfds;
int listen = _listen->get_handle();
while (true)
vector
vec;
_list->get_all(vec); // 獲得sock_list中的所有套介面控制代碼
init_readfds(vec, &readfds);
select(...);
// 檢查監聽套接字控制代碼,有新的連線到,建立新的連線
if (fd_isset(listen, &readfds))
tcp_comm* client = new tcp_comm;
_listen->accept(*client);
_list->insert(client);// 將已連線的套接字物件放到sock_list中
// 檢查所有的客戶端套接字控制代碼
vector
::iterator it;
for (it = vec.begin(); it != vec.end(); it++)
if (fd_isset((*it)->get_handle(), &readfds))
// 這裡是*it作為引數進行資料接收
為減少**量,我省去了出錯處理、細節;本來類都在某個命名空間中的,也省去了。
多程序(執行緒)和select合作
上面是在乙個程序中的情況,可以考慮多執行緒中每乙個執行緒實現select。以solaris 10為例,開100個執行緒,乙個執行緒支援1024個套介面,那就是100 * 1024,10萬個。集群服務中的前端均衡器的實現可以考慮一下這個技術,不過效率將是乙個極大的考驗。
結論本文重點講述在單程序的環境使用select支援多個客戶端。經常看見一些服務程式,用到了select也是來乙個連線,fork乙個子程序處理。在單程序中處理多個客戶端的目的是使開發的程式更易理解、維護;多程序往往較單程序複雜些。
IO模型 多路復用
乙個輸入操作通常包括兩個階段 應用程序被阻塞,直到資料從核心緩衝區複製到應用程序緩衝區中才返回。應該注意到,在阻塞的過程中,其它應用程序還可以執行,因此阻塞不意味著整個作業系統都被阻塞。因為其它應用程序還可以執行,所以不消耗 cpu 時間,這種模型的 cpu 利用率會比較高。應用程序執行系統呼叫之後...
IO模型 IO多路復用
用socket 一定會用到accept recv recvfrom這些方法 正常情況下 accept recv recvfrom都是阻塞的 如果setblocking false 整個程式就變成乙個非阻塞的程式了非阻塞的特點 沒有併發程式設計的機制 是乙個同步的程式 程式不會在某乙個連線的recv或...
IO模型 io多路復用(三)
兩者相互比較 1 如果只有乙個使用者連線server端,多路復用io還不如阻塞io效率高 2 相比阻塞io,多路復用io中間多了個反饋機制 3 多路復用io的 可以同時監控socket 多個socket物件coon1 coon2.recv 4 多路復用io可以識別有人連線某個coon3,然後告知有c...