zz用多路復用I O模型實現多個客戶端的通訊

2021-04-14 15:08:36 字數 2626 閱讀 4490

用多路復用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...