最近常看見關於完成端口的討論,對其實現頗爲好奇,於是經過多日連續奮戰,終於對完成端口進行了完整封裝,這裏談談我搭建的架構模型。
設計思路:
一、系統分爲工作線程,AcceptEx投遞線程,處理線程,資源回收線程四類線程
1.1、工作線程若干個,用於處理網絡事件方面工作,如處理:客戶端接收工作,數據接收
後進行簡單的分包並加入到請求包隊列中,數據發送完畢後負責檢查是否發送
完畢,沒有發完,則繼續發,發送完畢後,改變發送包標誌,由回收線程回收
1.2、AcceptEx投遞線程負責投遞AcceptEx,通過事件來檢測是否需要投遞新的AcceptEx
,同時,投遞的AcceptEx的數量會根據客戶端接收的情況動態更改,如果同時間
有很多客戶端在連接,會一次投遞更多的AcceptEx
1.3、處理線程負責處理請求包,線程依然有若干個,同時檢測請求包隊列,如果收到一個
請求包,則將其從隊列中取出,並做相應的業務處理.可以通過繼承CIOCPManager
並重載OnRequest來進行自己的處理。
處理線程中當然會有需要發送的數據,這時,調用CIOCPManager的函數SendBuffer
進行發送,個人覺得沒有必要設置一個發送線程來處理這些發送數據。
1.4、資源回收線程負責對系統的資源進行管理,主要有兩方面:1,對投遞的發送包進行
監測,回收一些已經發送完畢的發送包.2,對客戶端列表進行檢測,如果一個
客戶端的非活動時間超過一定範圍後,將客戶端關閉並回收
二、其他細節
2.1、關於工作線程和處理線程的數量,目前是根據系統允許的最大連接數來設置,使用
每200個客戶端使用一個工作線程,每100個客戶端使用一個工作線程,如果需要
更改,請修改配置文件,注意要將系統自動設置設置爲0
2.2、關於一次投遞AcceptEx的數量,默認是投遞10個,如果很短時間內有多個客戶端連接
那麼,每一次事件被激發後,投遞數量都比上一次多一倍,當然系統設有最大數量
在配置中可以修改.
三、使用方法
可以通過添加一個自定義的類,繼承自CIOCPManager類,重載OnRequest函數,在其中進行
響應的處理操作。
CTransFileServer Thread;
unsigned nThreadID = 0;
if(Thread.Init(_T("C://ICOPServer.ini")))
{
if(Thread.Listen())
{
//創建一個響應用戶操作的線程,用於停止客戶端
_beginthreadex(NULL, 0 ,ExitThread ,(void*)&Thread , 0, &nThreadID);
Thread.Run();
}
}
四、優化方法
1、減少memset的使用。該操作消耗cpu時間比較多,可以通過設置緩衝區內數據長度來控制。
2,使用優化的memcpy代替原來的memcpy,可以查看:
http://www.blogcn.com/user8/flier_lu/blog/1577430.html
http://www.blogcn.com/user8/flier_lu/blog/1577440.html
3,減少使用memcpy,收到數據後,可以一次封裝到請求包中時,直接拷貝過去,而不使用
先拷貝到接收緩衝區,然後在分析是否能封裝請求包。
4,處理線程應該是先掛起,當有請求時,將請求分給某一個掛起的線程,讓其處理。如果
所有線程都忙,應該新建處理線程。如果處理線程達到一定數量後,應該讓請求等待。
5,客戶端退出時,應該通知上層業務處理線程,以便刪除相關資源
6,查找一個掛起的處理線程目前還是順序查找,應該設計一種更好的查找算法