生活随笔
收集整理的這篇文章主要介紹了
                                
【网络编程】之十一、重叠IO Overlapped IO 完成例程
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.                        
 
                                
                            
                            
                             完成例程是Win Sockets提供的另一種管理完成的重疊I/O方法,完成例程是一個函數,當發起重疊操作時,將該函數傳遞給發起操作的函數,當重疊IO操作完成時由系統調用。
 
 下面來看一下例程必須擁有下面的函數原型:
 
 
 
   [cpp]?view plaincopy     
 void?CALLBACK?CompletionROUTINE{?? ????????IN?DWORD?dwError,???? ????????IN?DWORD?cbTransferred,???? ????????IN?LPWSAOVERLAPPED?lpOVerlapped,????? ????????IN?DWORD?dwFlags???? };?? 
 
 
 
 
 ? OK ,在應用程序中使用完成例程管理重疊IO操作時,你必須給調用函數制定一個完成例程,一個WSAOVERLAPPED結構,在這里WSAOVERLAPPED的hEvent字段不會被使用,因為你使用完成例程來管理重疊操作的最終結果。
 
 ? ?當我們的調用寫成在重疊操作完成后必須為完成例程提供服務,將調用線程置為“可警告的縣城等待狀態”。在這種狀態下,重疊IO操作完成時,完成例程也被調用。
 
 下面來看兩個函數,他們可以設置線程為一種可警告的等待狀態:
 
 WSAWatiForMultipleEvents
 
 
 
   [cpp]?view plaincopy     
 DWORD?WSAAPI?WSAWaitForMultipleEvents(???  DWORD?cEvents,??  const?WSAEVENT?FAR?*?lphEvents,??? ???BOOL?fWaitAll,??  DWORD?dwTimeout,??  BOOL?fAlertable?);?? 
 
 
 
如果函數成功,返回值指出造成函數返回的事件對象。
  如果函數失敗,返回值為WSA_WAIT_FAILED。
 
 
 
 來說一下最后一個參數,當為TRUE時,說明該函數返回時完成例程已經被執行。 ?如果該參數為FALSE,那么說明該函數返回時完成例程還沒有執行。
 
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?通過設置TRUE,將調用線程置于可警告的等待狀態,當該函數返回的時候,返回值為:WAIT_IO_COMPLETION。
 
 在這里,我們為了使用WSAWaitForMultipleEvents,在應用程序中可以定義一個不和任何對相關聯的事件對象。 ?然后我們用這個事件對象為參數來調用該函數。
 
 函數返回的時候,我們要判斷一下返回值是否是:WAIT_IO_COMPLETION,如果返回這個值,那么就說明這時候完成例程已經被調用了。如果不是,那么就說明發生了錯誤。
 
 
 
 SleepEx
 
 
 
   [cpp]?view plaincopy     
 DWORD?SleepEx{?? ??????DWORD?dwMilliseconds,?? ??????BOOL?bAlertable?? };?? 
 
 
 這里存在一個調用超時的問題,如果超時了,那么返回值就是0, ?如果發生了IO完成回調,那么函數就會返回,返回值是:WAIT_IO_COMPLETION。
 
 
 
 
 重疊io完成例程要求我們講一個瓦按成例程指定給發起IO操作的函數, ?當io操作完成后,完成例程就被調用。 ? ?下面來看一下開發win ?socket的步驟:
 
 1、創建具有WSAOVERLAPPED標志的套接字。
 
 2、定義完成例程。
 
 3、調用輸入或者輸出函數,初始化重疊IO操作,調用函數的最后一個參數為應用從程序定義的完成例程。
 
 4、調用WSAWaitForMultipleEvents()函數或者SleepEx()函數,使線程處于可警告的等待狀態。如果調用WSAWaitForMultipleEvents()函數 ?我們需要一個應用程序定義的事件對象,以便該函數等待事件的發生。這兩個函數的最后一個參數要設置為TRUE。
 
 5、當發生重疊IO回調時,完成例程被調用。
 
 
 
 
 
 
 
 下面來看一下WSAOVERLAPPED結構:
 
 
 
   [cpp]?view plaincopy     
 typedef?struct?<span?style="font-family:?Consolas,?Courier,?monospace;?line-height:?16px;?">_WSAOVERLAPPED</span>?{?? ??ULONG_PTR?Internal;?? ??ULONG_PTR?InternalHigh;?? ??union?{?? ????struct?{?? ??????DWORD?Offset;?? ??????DWORD?OffsetHigh;?? ????};?? ????PVOID??Pointer;?? ??};?? ??HANDLE????hEvent;?? }?<span?style="font-family:?Consolas,?Courier,?monospace;?line-height:?16px;?">WSAOVERLAPPED,?*LPWSAOVERLAPPED;</span>?? 
 
 
下面來看一下WSAOVERLAPPED結構的實例: 
 
 
 
 
   [cpp]?view plaincopy     
 #include?<winsock2.h>?? #include?<ws2tcpip.h>?? ?? #include?<stdio.h>?? #include?<stdlib.h>?? ?? ?? #pragma?comment(lib,?"ws2_32.lib")?? ?? int?__cdecl?main()?? {?? ?? ?????? ?????? ????WSADATA?wsaData;?? ????WSABUF?DataBuf;?? ?? ????WSAOVERLAPPED?Overlapped;?? ????SOCKET?SendToSocket?=?INVALID_SOCKET;?? ?? ????struct?sockaddr_in?RecvAddr;?? ????struct?sockaddr_in?LocalAddr;?? ????int?RecvAddrSize?=?sizeof?(RecvAddr);?? ????int?LocalAddrSize?=?sizeof?(LocalAddr);?? ?? ????u_short?Port?=?27015;?? ????struct?hostent?*localHost;?? ????char?*ip;?? ?? ????char?SendBuf[1024]?=?"Data?buffer?to?send";?? ????int?BufLen?=?1024;?? ????DWORD?BytesSent?=?0;?? ????DWORD?Flags?=?0;?? ?? ????int?rc,?err;?? ????int?retval?=?0;?? ?? ?????? ?????? ?????? ????rc?=?WSAStartup(MAKEWORD(2,?2),?&wsaData);?? ????if?(rc?!=?0)?{?? ????????printf("Unable?to?load?Winsock:?%d\n",?rc);?? ????????return?1;?? ????}?? ?? ?????? ????SecureZeroMemory((PVOID)&Overlapped,?sizeof(WSAOVERLAPPED));?? ?? ?????? ????Overlapped.hEvent?=?WSACreateEvent();?? ????if?(Overlapped.hEvent?==?NULL)?{?? ????????printf("WSACreateEvent?failed?with?error:?%d\n",?WSAGetLastError());?? ????????WSACleanup();?? ????????return?1;?? ????}?? ?????? ?????? ????SendToSocket?=?? ????????WSASocket(AF_INET,?SOCK_DGRAM,?IPPROTO_UDP,?NULL,?0,?? ??????????????????WSA_FLAG_OVERLAPPED);?? ????if?(SendToSocket?==?INVALID_SOCKET)?{?? ????????printf("socket?failed?with?error:?%d\n",?WSAGetLastError());?? ????????WSACloseEvent(Overlapped.hEvent);?? ????????WSACleanup();?? ????????return?1;?? ????}?? ?????? ?????? ?????? ?????? ????RecvAddr.sin_family?=?AF_INET;?? ????RecvAddr.sin_port?=?htons(Port);?? ????RecvAddr.sin_addr.s_addr?=?inet_addr("127.0.0.1");?? ?? ?????? ?????? ?????? ????localHost?=?gethostbyname("");?? ????ip?=?inet_ntoa(*(struct?in_addr?*)?*localHost->h_addr_list);?? ?? ????LocalAddr.sin_family?=?AF_INET;?? ????LocalAddr.sin_addr.s_addr?=?inet_addr(ip);?? ????LocalAddr.sin_port?=?htons(Port);?? ?? ?????? ?????? ?????? ?????? ????rc?=?bind(SendToSocket,?(struct?sockaddr?*)?&LocalAddr,?LocalAddrSize);?? ????if?(rc?==?SOCKET_ERROR)?{?? ????????printf("bind?failed?with?error:?%d\n",?WSAGetLastError());?? ????????WSACloseEvent(Overlapped.hEvent);?? ????????closesocket(SendToSocket);?? ????????WSACleanup();?? ????????return?1;?? ????}?? ?????? ?????? ????printf("Sending?a?datagram...\n");?? ????DataBuf.len?=?BufLen;?? ????DataBuf.buf?=?SendBuf;?? ????rc?=?WSASendTo(SendToSocket,?&DataBuf,?1,?? ???????????????????&BytesSent,?Flags,?(SOCKADDR?*)?&?RecvAddr,?? ???????????????????RecvAddrSize,?&Overlapped,?NULL);?? ?? ????if?((rc?==?SOCKET_ERROR)?&&?(WSA_IO_PENDING?!=?(err?=?WSAGetLastError())))?{?? ????????printf("WSASendTo?failed?with?error:?%d\n",?err);?? ????????WSACloseEvent(Overlapped.hEvent);?? ????????closesocket(SendToSocket);?? ????????WSACleanup();?? ????????return?1;?? ????}?? ?? ????rc?=?WSAWaitForMultipleEvents(1,?&Overlapped.hEvent,?TRUE,?INFINITE,?TRUE);?? ????if?(rc?==?WSA_WAIT_FAILED)?{?? ????????printf("WSAWaitForMultipleEvents?failed?with?error:?%d\n",?? ????????????????WSAGetLastError());?? ????????retval?=?1;?? ????}?? ?? ????rc?=?WSAGetOverlappedResult(SendToSocket,?&Overlapped,?&BytesSent,?? ????????????????????????????????FALSE,?&Flags);?? ????if?(rc?==?FALSE)?{?? ????????printf("WSASendTo?failed?with?error:?%d\n",?WSAGetLastError());?? ????????retval?=?1;?? ????}?? ?? ?????? ?????? ????printf("Finished?sending.?Closing?socket.\n");?? ????WSACloseEvent(Overlapped.hEvent);?? ????closesocket(SendToSocket);?? ????printf("Exiting.\n");?? ?? ?????? ?????? ????WSACleanup();?? ????return?(retval);?? }?? 
 
 
WSAOVERLAPPED ? 和 ?WSAGetOverlappedResult在上一節中都給出過:
http://blog.csdn.net/jofranks/article/details/7895316
 
 
 
 
 
 
 
 
                  ?----2012/9/20
  ----jofranks 于南昌
 
 
                            總結
                            
                                以上是生活随笔為你收集整理的【网络编程】之十一、重叠IO Overlapped IO 完成例程的全部內容,希望文章能夠幫你解決所遇到的問題。
                            
                            
                                如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。