在Windows系統裡,使用完成連接埠是高效能的方法之一,比如把完成連接埠使用到線程池和網路伺服器裡。現在就通過線程池的方法來介紹怎麼樣使用完成連接埠,高效能的伺服器以後再仔細地介紹怎麼樣構造它。其實完成連接埠是一個隊列,所有的線程都在等訊息出現,如果隊列裡有訊息,就每個線程去擷取一個訊息執行它。先用函數CreateIoCompletionPort來建立一個訊息佇列,然後使用GetQueuedCompletionStatus函數來從隊列擷取訊息,使用函數PostQueuedCompletionStatus來向隊列裡發送訊息。通過這三個函數就實現完成連接埠的訊息迴圈處理。
函數CreateIoCompletionPort、GetQueuedCompletionStatus、PostQueuedCompletionStatus聲明如下:
WINBASEAPI
__out
HANDLE
WINAPI
CreateIoCompletionPort(
__in HANDLE FileHandle,
__in_opt HANDLE ExistingCompletionPort,
__in ULONG_PTR CompletionKey,
__in DWORD NumberOfConcurrentThreads
);
WINBASEAPI
BOOL
WINAPI
GetQueuedCompletionStatus(
__in HANDLE CompletionPort,
__out LPDWORD lpNumberOfBytesTransferred,
__out PULONG_PTR lpCompletionKey,
__out LPOVERLAPPED *lpOverlapped,
__in DWORD dwMilliseconds
);
WINBASEAPI
BOOL
WINAPI
PostQueuedCompletionStatus(
__in HANDLE CompletionPort,
__in DWORD dwNumberOfBytesTransferred,
__in ULONG_PTR dwCompletionKey,
__in_opt LPOVERLAPPED lpOverlapped
);
FileHandle是關聯的檔案控制代碼。
ExistingCompletionPort是已經存在的完成連接埠。
CompletionKey是傳送給處理函數的參數。
NumberOfConcurrentThreads是有多少個線程在訪問這個訊息佇列。
CompletionPort是已經存在的完成連接埠。
lpCompletionKey是傳送給處理函數的參數。
lpOverlapped是傳送給處理函數的參數。
dwMilliseconds是等待時間。
dwNumberOfBytesTransferred是傳送了多少個位元組。
調用函數的例子如下:
#001 #pragma once
#002
#003 #include "Thread.h"
#004
#005
#006 //使用IOCP實現線程池。
#007 //蔡軍生 2007/10/29 QQ:9073204 深圳
#008 class CThreadPools
#009 {
#010 public:
#011
#012 CThreadPools(void)
#013 {
#014 m_nThreadCount = 2;
#015 }
#016
#017 ~CThreadPools(void)
#018 {
#019 }
#020
#021 bool Init(void)
#022 {
#023 //建立一個IOCP。
#024 m_hQueue = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, m_nThreadCount);
#025 if (m_hQueue == NULL)
#026 {
#027 //建立IOCP失敗。
#028 return false;
#029 }
#030 }
#031
#032 int GetThreadCount(void) const
#033 {
#034 return m_nThreadCount;
#035 }
#036
#037 //線程池處理的內容。
#038 DWORD Run(void)
#039 {
#040 DWORD dwBytesTransfered;
#041 ULONG_PTR dwCompletionKey;
#042
#043 OVERLAPPED* pOverlapped;
#044
#045 //等一個IOCP的訊息。
#046 while (GetQueuedCompletionStatus(m_hQueue, &dwBytesTransfered, &dwCompletionKey, &pOverlapped, INFINITE))
#047 {
#048 if (pOverlapped == ((OVERLAPPED*) ((__int64) -1)) )
#049 {
#050 //退出。
#051 OutputDebugString(_T("退出 \r\n"));
#052 break;
#053 }
#054 else
#055
#056 {
#057 WPARAM request = (WPARAM) dwCompletionKey;
#058
#059 //處理訊息。
#060 OutputDebugString(_T("GetQueuedCompletionStatus \r\n"));
#061 }
#062 }
#063
#064 return 0;
#065 }
#066
#067 //發送處理的訊息。
#068 bool QueueRequest(WPARAM wParam)
#069 {
#070 //往IOCP裡發送一條訊息。
#071 if (!PostQueuedCompletionStatus(m_hQueue, 0, (ULONG_PTR) wParam, NULL))
#072 {
#073 return false;
#074 }
#075
#076 return true;
#077 }
#078
#079 //關閉所有線程。
#080 void Close(void)
#081 {
#082 for (int i = 0; i < m_nThreadCount; i++)
#083 {
#084 PostQueuedCompletionStatus(m_hQueue, 0, 0, (OVERLAPPED*) ((__int64) -1) );
#085 }
#086 }
#087
#088 protected:
#089 //接收訊息處理的隊列。
#090 HANDLE m_hQueue;
#091
#092 //線程個數。
#093 int m_nThreadCount;
#094 };
#095
#096 //////////////////////////////////////////////////////////////////////////
#097 class CThreads :
#098 public CThread
#099 {
#100 public:
#101 CThreads(CThreadPools* pPool)
#102 {
#103 m_pPool = pPool;
#104 }
#105 virtual ~CThreads(void)
#106 {
#107
#108 }
#109
#110
#111 protected:
#112 //
#113 //線程運行函數。
#114 //在這裡可以使用類裡的成員,也可以讓衍生類別實現更強大的功能。
#115 //蔡軍生 2007/10/29
#116 virtual DWORD Run(void)
#117 {
#118 //
#119 if (m_pPool)
#120 {
#121 return m_pPool->Run();
#122 }
#123
#124 return -1;
#125 }
#126
#127 protected:
#128 CThreadPools* m_pPool;
#129
#130 };
本文來自CSDN部落格,轉載請標明出處:http://blog.csdn.net/caimouse/archive/2007/10/29/1855142.aspx