標籤:緩衝區 infinite 存在 相同 數組 資料結構 程式員 window event
1.適用於除Windows CE之外的各種Windows平台.在使用這個模型之前應該確保該系統安裝了Winsock2.重疊模型的基本設計原理是使用一個重疊的資料結構,一次投遞一個或多個Winsock I/O請求。在重疊模型中,收發資料使用WSA開頭的函數。
2.WSA_FLAG_OVERLAPPED標誌:要使用重疊模型。在建立通訊端的時候,必須加上該標誌。
SOCKET s=WSASocket(AF_INET,SOCK_STREAM,0,NULL,0,WSA_FLAG_OVERLAPPED);
假如使用的是socket函數,而非WSASocket函數,那麼會預設設定WSA_FLAG_OVERLAPPED標誌。
若隨一個WSAFLAGOVERLAPPED結構一起調用這些以WSA開頭的函數(AcceptEx和TRansmiteFile函數例外),函數會立即完成並返回,無論通訊端是否設為阻塞模式
3.重疊模型在網路事件完成後,可以有兩種方式通知應用程式:事件通知和完成常式
3.事件通知:事件對象與WSAOVERLAPPED進行綁定實現網路事件完成後通過事件進行通知。
4.WSAOVERLAPPED結構:
typedef struct WSAOverlapped
{
DWORD Internal;
DOWRD InternalHigh;
DWORD Offset;
DWORD OffsetHigh;
WSAEVENT hEvent;
}WSAOVERLAPPED,FAR* LPWSAOVERLAPPED;
此處,程式員可以使用的是最後一個參數hEvent,其餘的不用管。通過該參數,重疊結構可以與事件對象進行綁定,以實現網路事件完成後,通過事件對象進行通知應用程式。事件對象通知方式是通過建立一個事件對象,把該對象賦值給重疊結構的hEvent參數即可實現綁定。在此再次提醒大家注意:WSAWaitForMultipleEvents函數一次最多隻能等待64個事件對象。
5.WSAGetOverlappedResult函數:重疊請求完成後,接著需要調用WSAGetOverlappedResult(取得重疊結構)函數,判斷那個重疊調用到底是成功,還是失敗.
BOOL WSAGetOverlappedResult(
SOCKET s,//通訊端
LPWSAOVERLAPPED lpOverlapped,//重疊結構
LPDWORD lpcbTransfer,//對應一個DWORD(雙位元組)變數,一次重疊實際傳輸(接收或者發送)的位元組數
BOOL fWait,//參數用於決定函數是否應該等待一次重疊操作完成。
LPWORD lpdwFlags
);
重疊操作完成,函數返回TRUE,否則,返回FALSE。返回FALSE通常都是有一下幾種情況造成的.
(1)重疊I/O操作仍處在未完成狀態
(2)重疊操作已經完成,但含有錯誤
(3)重疊操作的完成狀態不可判決,因為在提供給函數WSAGetOverlappedResult的一個或多個參數中,存在著錯誤。
失敗後,由lpcbTransfer參數指向的值不會進行更新,而且我們的應用程式應調用WSAGetLastError函數
6.基於事件通知的重疊模型編程步驟如下:
(1) 建立一個通訊端,綁定本機連接埠,在指定的連接埠上監聽串連請求。
(2)接受串連請求。
(3)為接受的通訊端建立一個WSAOVERLAPPED結構,並為該結構分配一個事件物件控點。也將事件物件控點分配給一個事件數目組,以便稍後由函數WSAWaitForMultipleEvents使用。
(4)在通訊端上投遞一個非同步WSARecv請求,指定參數為WSAOVERLAPPED結構。注意函數通常會以失敗告終,返回SOCKETERROR錯誤狀態WSAIOPENDING(I/O操作尚未完成)。
(5)使用步驟3)的事件數目組,調用WSAWaitForMultipleEvents函數,並等待與重疊調用關聯在一起的事件進入“已傳信”狀態(換言之,等待那個事件的“觸發”)。
(6)WSAWaitForMultipleEvents函數完成後,針對事件數目組,調用WSAResetEvent(重設事件)函數,從而重設事件對象,並對完成的重疊請求進行處理。
(7)使用WSAGetOverlappedResult函數,判斷重疊調用的返回狀態是什麼。
(8)在通訊端上投遞另一個重疊WSARecv請求。
(9)重複步驟5 ) ~ 8 )。
範例程式碼:
1 void main(void) 2 { 3 WSABUF databuf; 4 DWORD eventTotal=0; 5 WSAEVENT eventArray[WSA_MAXIMUM_WAIT_EVENTS]; 6 WSAOVERLAPPED acceptOverlapped; 7 SOCKET listensock,acceptsock; 8 9 10 //初始化工作和一般socket通訊相同 11 ...12 13 //接收串連14 acceptsock=accept(listensock,NULL,NULL);15 16 //建立事件,綁定事件對象與重疊結構17 eventArray[eventTotal]=WSACreateEvent();18 ZeroMemory(&acceptOverlapped,sizeof(WSAOVERLAPPED));19 acceptOverlapped.hEvent=eventArray[eventTotal];20 21 //資料緩衝區初始化22 databuf.len=DATA_BUFSIZE;23 databuf.buf=buffer;24 25 eventTotal++;26 27 //投遞接收請求28 WSARecv(acceptsock,&databuf,1,&recvBytes,&flags,&acceptOverlapped,NULL);29 30 while(1)31 {32 //監視事件對象狀態33 index=WSAWaitForMultipleEvents(eventTotal,eventArray,FALSE,WSA_INFINITE,FALSE);34 35 //人工儲值事件36 WSAResetEvent(eventArray[eventTotal-WSA_WAIT_EVENT_0]);37 38 //擷取I/O操作的完成情況39 WSAGetOverlappedResult(acceptsock,&acceptOverlapped,&bytesTransferred,FALSE,&flag);40 41 if(bytesTransferred==0)42 {43 closesocket(acceptsock);44 WSACloseEvent(eventArray[eventTotal-WSA_WAIT_EVENT_0]);45 return;46 }47 48 //處理接收過來的資料49 ...50 51 //再再次發送一個WSARecv請求52 flag=0;53 ZeroMemory(&acceptOverlapped,sizeof(WSAOVERLAPPED));54 55 databuf.LEN=DATA_BUFSIZE;56 databuf.buf=buf;57 WSARecv(acceptsock,&databuf,1,&recvbytes,&flag,&acceptOverlapped,NULL);58 }59 60 }
View Code
注意:對於接受用戶端串連的函數,還有一個AcceptEx函數,不過這個函數太過麻煩且對效能的提升沒有太大的作用,暫時不打算學習
接下來學習基於完成常式的重疊IO模型:
四.Windows I/O模型之重疊IO(overlapped)模型