常見的網路通訊分為兩種:同步和非同步。
在同步通訊中,每一次接受資料都會導致主線程的掛起,從而阻塞住了其他操作。為了解決這一問題,我們通常會採取同步通訊+多執行緒的策略,即為每乙個連入的socket分配乙個執行緒。然而隨著連入的socket的數量的增加,執行緒的數量也在增加,這樣cpu則需要不停地進行執行緒的切換,因此難以成為高效能的伺服器程式。
非同步通訊則可以把接收資料這一操作交給核心,即在核心接收資料的時候,主線程可以不用被阻塞並且繼續執行其他操作,而一旦接收資料完成以後,再由核心通知主線程。而如何通知主線程是乙個關鍵,不同的非同步通訊策略有著不同的通知方式。
在這樣的情況下,完成埠這一i/o模型被提出,成為目前windows下效能最好的i/o模型之一。
首先根據cpu數量開好執行緒,當有使用者請求的時候,把這些請求加入乙個特定的訊息佇列中,而事先開好的執行緒則會排隊從這個訊息佇列中獲取請求並作出處理。完成埠正是指這一訊息佇列.
// socket的控制代碼,置為invalid_handle_value表示建立乙個沒有和任何handle有關係的完成埠
_in_opt handle existingcompletionport,
// null表示新建乙個完成埠
_in_ ulong_ptr completionkey,
// 完成鍵,建立完成埠時置為0
_in_ dword numberofconcurrentthreads
// 完成埠併發執行緒的數量,置0表示有多少個cpu就開多少個執行緒
);
初始化socket庫...
......
繫結埠,並監聽...
createiocompletionport(listensoc, iocp, compkey, 0);
handle winapi createiocompletionport(
_in_ handle filehandle,
// 監聽socket的控制代碼
_in_opt handle existingcompletionport,
// 剛才建立的完成埠
_in_ ulong_ptr completionkey,
// 完成鍵,我們在繫結的同時為其分配一段記憶體空間,以儲存與這一socket相關的資訊,當網路操作完成的時候,我們可以根據這段記憶體空間裡面的資訊分辨這是哪乙個socket
_in_ dword numberofconcurrentthreads
// 完成埠併發執行緒的數量,置0表示有多少個cpu就開多少個執行緒
);
acceptex採取非同步方式,可以同時投遞多個請求,而accept採取阻塞的方式,依次只能處理乙個請求。
acceptex會事先準備好socket,當使用者請求連入的時候直接使用這一新的socket,避免臨時建立socket。
acceptex接受連入請求的同時,我們可以附加一些資料,這樣我們就可以在接受使用者連入的同時,接受來自使用者的第一組資料。
bool acceptex (
socket slistensocket, // 監聽socket
socket sacceptsocket, // 事先準備好給新使用者的socket
pvoid lpoutputbuffer, // 接受緩衝區
dword dwreceivedatalength, // 用於存放使用者第一組資料的空間大小
dword dwlocaladdresslength, // 本地位址的空間大小
dword dwremoteaddresslength, // 客戶端位址的空間大小
lpdword lpdwbytesreceived,
// 重疊結構,每乙個網路操作都會對應乙個重疊結構,相當於網路操作的id
);
int wsarecv(
socket s, // 接受資料的socket
lpwsabuf lpbuffers, // 接收緩衝區
dword dwbuffercount, // 置為1
lpdword lpnumberofbytesrecvd, // 所接收到的位元組數
lpdword lpflags, // 置為0
null
);
void getacceptexsockaddrs(
_in_ pvoid lpoutputbuffer,
// acceptex中的緩衝區
_in_ dword dwreceivedatalength,
// 使用者第一組資料的空間大小
_in_ dword dwlocaladdresslength,
// 本地位址的空間大小
_in_ dword dwremoteaddresslength,
// 客戶端位址的空間大小
_out_ lpsockaddr *localsockaddr,
// 本地位址
_out_ lpint localsockaddrlength,
// 實際本地位址的空間大小
_out_ lpsockaddr *remotesockaddr,
// 客戶端位址
_out_ lpint remotesockaddrlength
// 實際客戶端位址的大小
);
參考: 1. 完成埠(completionport)詳解 - 手把手教你玩轉網路程式設計系列之三
Linux下和Windows下的效能監控
uptime命令 top命令 可以知道每個程序佔cpu的情況 total 程序總數 running 正在執行的程序數 sleeping 睡眠的程序數 stopped 停止的程序數 zombie 殭屍程序數 cpu s 0.1 us 使用者空間占用cpu百分比 0.2 sy 核心空間占用cpu百分比 ...
LINUX下磁碟IO效能監測分析
linux下磁碟io效能監測分析 2011 08 16 18 10 23 標籤 效能監測分析 linux 磁碟io 休閒suse linux 這兩天發現一台測試用的伺服器經常負載很高,但cpu和記憶體消耗卻很少,很是奇怪,經過診斷發現是由於大容量的測試資料導致高併發下的磁碟io消耗比較大,由於快取是...
SUSE LINUX下磁碟IO效能監測分析
這兩天發現一台測試用的伺服器經常負載很高,但cpu和記憶體消耗卻很少,很是奇怪,經過診斷發現是由於大容量的測試資料導致高併發下的磁碟io消耗比較大,由於快取是小檔案並且數量比較大,所以併發比較高的情況下io消耗非常大。那怎樣才能快速的定位到併發高是由於磁碟io開銷大呢?一 用 top 命令中的 資訊...