日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【网络编程】之十一、重叠IO Overlapped IO 完成例程

發布時間:2024/4/11 编程问答 50 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【网络编程】之十一、重叠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,//The?number?of?event?object?handles?in?the?array?pointed?to?by?lphEvents.?WSA_MAXIMUM_WAIT_EVENTS是句柄最大值??
  •  const?WSAEVENT?FAR?*?lphEvents,?//A?pointer?to?an?array?of?event?object?handles.??
  • ???BOOL?fWaitAll,//?the?wait?type!TURE:當lphEvents的所有對象有信號的時候函數返回。FALSE:當任意一個事件對象有信號時函數返回??
  •  DWORD?dwTimeout,//The?time-out?interval,秒為單位??
  •  BOOL?fAlertable?);//指定當系統將一個輸入/輸出完成例程放入隊列以供執行時,函數是否返回。TRUE:函數返回并執行完成例程FALSE:函數不返回也不執行完成例程。??
  • 如果函數成功,返回值指出造成函數返回的事件對象。   如果函數失敗,返回值為WSA_WAIT_FAILED。

    來說一下最后一個參數,當為TRUE時,說明該函數返回時完成例程已經被執行。 ?如果該參數為FALSE,那么說明該函數返回時完成例程還沒有執行。

    ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?通過設置TRUE,將調用線程置于可警告的等待狀態,當該函數返回的時候,返回值為:WAIT_IO_COMPLETION。

    在這里,我們為了使用WSAWaitForMultipleEvents,在應用程序中可以定義一個不和任何對相關聯的事件對象。 ?然后我們用這個事件對象為參數來調用該函數。

    函數返回的時候,我們要判斷一下返回值是否是:WAIT_IO_COMPLETION,如果返回這個值,那么就說明這時候完成例程已經被調用了。如果不是,那么就說明發生了錯誤。

    SleepEx

    [cpp]?view plaincopy
  • DWORD?SleepEx{??
  • ??????DWORD?dwMilliseconds,//等待時間,ms為單位,???INFINITE說明函數將無限等待??
  • ??????BOOL?bAlertable//函數的返回方式1、FALSE,在不調用超時的情況下是不返回的。2、TRUE?調用超時或者?????????????????????//發生IO回調,那么就返回。??
  • };??

  • 這里存在一個調用超時的問題,如果超時了,那么返回值就是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;//os保留,指出一個和系統相關的狀態??
  • ??ULONG_PTR?InternalHigh;//發送,接收數據的長度??
  • ??union?{??
  • ????struct?{??
  • ??????DWORD?Offset;//文件的初始位置??
  • ??????DWORD?OffsetHigh;//文件的偏移量??
  • ????};??
  • ????PVOID??Pointer;//指向文件傳送位置,<span?style="color:?rgb(42,?42,?42);?font-family:?'Segoe?UI',?'Lucida?Grande',?Verdana,?Arial,?Helvetica,?sans-serif;?line-height:?18px;?">do?not?use?after?initialization?to?zero.</span>??
  • ??};??
  • ??HANDLE????hEvent;//指定一個IO操作完成后觸發的事件??
  • }?<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>??
  • ??
  • //?Need?to?link?with?Ws2_32.lib??
  • #pragma?comment(lib,?"ws2_32.lib")??
  • ??
  • int?__cdecl?main()??
  • {??
  • ??
  • ????//---------------------------------------------??
  • ????//?Declare?and?initialize?variables??
  • ????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;??
  • ??
  • ????//---------------------------------------------??
  • ????//?Initialize?Winsock??
  • ????//?Load?Winsock??
  • ????rc?=?WSAStartup(MAKEWORD(2,?2),?&wsaData);??
  • ????if?(rc?!=?0)?{??
  • ????????printf("Unable?to?load?Winsock:?%d\n",?rc);??
  • ????????return?1;??
  • ????}??
  • ??
  • ????//?Make?sure?the?SendOverlapped?struct?is?zeroed?out??
  • ????SecureZeroMemory((PVOID)&Overlapped,?sizeof(WSAOVERLAPPED));??
  • ??
  • ????//?Create?an?event?handle?and?setup?the?overlapped?structure.??
  • ????Overlapped.hEvent?=?WSACreateEvent();??
  • ????if?(Overlapped.hEvent?==?NULL)?{??
  • ????????printf("WSACreateEvent?failed?with?error:?%d\n",?WSAGetLastError());??
  • ????????WSACleanup();??
  • ????????return?1;??
  • ????}??
  • ????//---------------------------------------------??
  • ????//?Create?a?socket?for?sending?data??
  • ????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;??
  • ????}??
  • ????//---------------------------------------------??
  • ????//?Set?up?the?RecvAddr?structure?with?the?IP?address?of??
  • ????//?the?receiver?(in?this?example?case?"127.0.0.1")??
  • ????//?and?the?specified?port?number.??
  • ????RecvAddr.sin_family?=?AF_INET;??
  • ????RecvAddr.sin_port?=?htons(Port);??
  • ????RecvAddr.sin_addr.s_addr?=?inet_addr("127.0.0.1");??
  • ??
  • ????//---------------------------------------------??
  • ????//?Set?up?the?LocalAddr?structure?with?the?local?IP?address??
  • ????//?and?the?specified?port?number.??
  • ????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);??
  • ??
  • ????//---------------------------------------------??
  • ????//?Bind?the?sending?socket?to?the?LocalAddr?structure??
  • ????//?that?has?the?internet?address?family,?local?IP?address??
  • ????//?and?specified?port?number.????
  • ????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;??
  • ????}??
  • ????//---------------------------------------------??
  • ????//?Send?a?datagram?to?the?receiver??
  • ????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;??
  • ????}??
  • ??
  • ????//---------------------------------------------??
  • ????//?When?the?application?is?finished?sending,?close?the?socket.??
  • ????printf("Finished?sending.?Closing?socket.\n");??
  • ????WSACloseEvent(Overlapped.hEvent);??
  • ????closesocket(SendToSocket);??
  • ????printf("Exiting.\n");??
  • ??
  • ????//---------------------------------------------??
  • ????//?Clean?up?and?quit.??
  • ????WSACleanup();??
  • ????return?(retval);??
  • }??

  • WSAOVERLAPPED ? 和 ?WSAGetOverlappedResult在上一節中都給出過: http://blog.csdn.net/jofranks/article/details/7895316


    ?----2012/9/20

    ----jofranks 于南昌


    總結

    以上是生活随笔為你收集整理的【网络编程】之十一、重叠IO Overlapped IO 完成例程的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。