?? 6-5.html
字號:
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=gb_2312-80">
<META NAME="Generator" CONTENT="Microsoft Word 97">
<TITLE>6</TITLE>
</HEAD>
<BODY>
<B><FONT FACE="黑體" LANG="ZH-CN" SIZE=5><P><A NAME="_Toc336626888"><A NAME="_Toc336792971"><A NAME="_Toc336793447"></FONT><FONT FACE="Arial" SIZE=5>6.5 </FONT><FONT FACE="黑體" LANG="ZH-CN" SIZE=5>重疊</FONT><FONT FACE="Arial" SIZE=5>I/O</FONT><FONT FACE="黑體" LANG="ZH-CN" SIZE=5>和事件對象</A></A></A></P>
</B></FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3><P ALIGN="JUSTIFY">	</FONT><FONT SIZE=3>Windows Sockets 2</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>引入了重疊</FONT><FONT SIZE=3>I/O</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>的概念并且要求所有的傳輸協議提供者都支持這一功能。重疊</FONT><FONT SIZE=3>I/O</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>僅能在由</FONT><FONT SIZE=3>WSASocket()</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>函數打開的套接口上使用(使用</FONT><FONT SIZE=3>WSA_FLAG_OVERLAPPED</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>標記)。這種方式的使用將采用</FONT><FONT SIZE=3>Win32</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>建立的模型。</P>
<P ALIGN="JUSTIFY">	對于接收,應用程序使用</FONT><FONT SIZE=3>WSARecv()</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>函數或</FONT><FONT SIZE=3>WSARecvFrom()</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>函數來提供存放接收數據的緩沖區。如果數據在網絡接收以前,應用程序已經提供了一個或多個數據緩沖區,那么接收的數據就可以立即被存放進用戶緩沖區。這樣可以省去使用</FONT><FONT SIZE=3>recv()</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>函數和</FONT><FONT SIZE=3>recvfrom()</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>函數時需要進行的拷貝工作。如果在應用程序提供數據緩沖區時已經有數據到來,那么接收的數據將被立即拷貝進用戶緩沖區。如果數據到來時,應用程序沒有提供接收緩沖區,那么網絡將回到我們熟悉的同步操作方式-傳送來的數據將被存放進內部緩沖區,直到應用程序發出了接收調用并且提供了接收緩沖區,這時接收的數據就被拷貝進接收緩沖區。這種做法會有一個例外:就是當應用程序使用</FONT><FONT SIZE=3>setsockopt()</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>函數把接收緩沖區長度置為了</FONT><FONT SIZE=3>0</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>。在這種情況下,對于可靠傳輸協議,只有在應用程序提供了接收數據緩沖區后,數據才會被接收;而對于不可靠傳輸協議,數據將會丟失。</P>
<P ALIGN="JUSTIFY">	對于發送的一方,應用程序使用</FONT><FONT SIZE=3>WSASend()</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>函數或</FONT><FONT SIZE=3>WSASendTo()</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>函數提供一個指向已填充的數據緩沖區的指針。應用程序不應在網絡使用完該緩沖區的數據以前以任何方式破壞該緩沖區的數據。</P>
<P ALIGN="JUSTIFY">	重疊發送和接收調用會立即返回。如果返回值是</FONT><FONT SIZE=3>0</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>,那么表明了</FONT><FONT SIZE=3>I/O</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>操作已經完成,對應的完成指示也已經可以得到。如果返回值是</FONT><FONT SIZE=3>SOCKET_ERROR</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>,并且錯誤代碼是</FONT><FONT SIZE=3>WSA_IO_PENDING</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>,那么表明重疊操作已經被成功地初始化,今后發送緩沖區被用完或者接收緩沖區被填滿時,將會有完成指示。任何其他的錯誤代碼表明了初始化沒有成功,今后也不會有什么完成指示。</P>
<P ALIGN="JUSTIFY">	發送操作和接收操作都可以被重疊使用。接收函數可以被多次調用,發出接收緩沖區,準備接收到來的數據。發送函數也可以被多次調用,組成一個發送緩沖區隊列。要注意的是,應用程序可以通過按順序提供發送緩沖區來確保一系列重疊發送操作的順序,但是對應的完成指示有可能是按照另外的順序排列的。同樣的,在接收數據的一方,緩沖區是按照被提供的順序填充的,但是完成指示也可能按照另外的順序排列。</P>
<P ALIGN="JUSTIFY">	</FONT><FONT SIZE=3>WSAIoctl()</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>函數(</FONT><FONT SIZE=3>ioctolsocket()</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>函數的增強版本)還可以使用重疊</FONT><FONT SIZE=3>I/O</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>操作的延遲完成特性。</P>
<P ALIGN="JUSTIFY"> </P>
</FONT><B><FONT FACE="宋體" LANG="ZH-CN" SIZE=5><P><A NAME="_Toc336626889"><A NAME="_Toc336792972"><A NAME="_Toc336793448"></FONT><FONT SIZE=5>6.5.1 </FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=5>事件對象</A></A></A></P>
</B></FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3><P ALIGN="JUSTIFY">	重疊</FONT><FONT SIZE=3>I/O</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>概念的引入需要建立一個機制使得應用程序能夠正確的把發送和接收事件與今后它們完成時的指示相連接。在</FONT><FONT SIZE=3>Windows Sockets 2</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>中,這一點是通過事件對象實現的,它采用了</FONT><FONT SIZE=3>Win32</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>事件的模型。</FONT><FONT SIZE=3>Windows Sockets</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>事件對象是一個相當簡單的結構,它可以被創建,關閉,設置,清除,等待和檢查。它們的主要用處是使得應用程序能夠阻塞并等待直到一個或多個事件對象被設置。</P>
<P ALIGN="JUSTIFY">	應用程序可以使用</FONT><FONT SIZE=3>WSACreateEvent()</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>函數來得到一個事件對象句柄,這個句柄可以作為以后的重疊發送和接收函數的輸入參數(</FONT><FONT SIZE=3>WSASend()</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>,</FONT><FONT SIZE=3>WSASendTo()</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>,</FONT><FONT SIZE=3>WSARecv()</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>,</FONT><FONT SIZE=3>WSARecvFrom()</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>)。事件對象在創建時被清除,在相關的重疊</FONT><FONT SIZE=3>I/O</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>操作完成時由傳輸協議提供者設置(或者成功,或者出錯)。每個被</FONT><FONT SIZE=3>WSACreateEvent()</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>函數創建的事件對象都必須有對應的</FONT><FONT SIZE=3>WSACloseEvent()</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>函數釋放它。</P>
<P ALIGN="JUSTIFY">	</FONT><FONT SIZE=3>WSAEventSelect()</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>函數把一個或多個</FONT><FONT SIZE=3>FD_XXX</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>網絡事件與一個事件對象連接。這將在</FONT><FONT SIZE=3>2.6</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>中討論。</P>
<P ALIGN="JUSTIFY">	在</FONT><FONT SIZE=3>32</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>位環境中,與事件對象相關的函數,包括</FONT><FONT SIZE=3>WSACreateEvent()</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>,</FONT><FONT SIZE=3>WSACloseEvent()</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>,</FONT><FONT SIZE=3>WSASetEvent()</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>,</FONT><FONT SIZE=3>WSAResetEvent()</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>,</FONT><FONT SIZE=3>WSAWaitForMultipleEvent()</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>和</FONT><FONT SIZE=3>WSAGetOverlappedResult()</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>,都被直接映射到對應的</FONT><FONT SIZE=3>Win32</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>函數,例如沒有</FONT><FONT SIZE=3>WSA</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>前綴的同名函數。</P>
<P ALIGN="JUSTIFY"> </P>
</FONT><B><FONT FACE="宋體" LANG="ZH-CN" SIZE=5><P><A NAME="_Toc336626890"><A NAME="_Toc336792973"><A NAME="_Toc336793449"></FONT><FONT SIZE=5>6.5.2 </FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=5>接收操作完成指示</A></A></A></P>
</B></FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3><P ALIGN="JUSTIFY">	為了提供給應用程序適當的靈活性,</FONT><FONT SIZE=3>Windows Sockets 2</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>為接收操作完成指示提供了多個選項。它們包括:等待(阻塞)事件對象,檢查事件對象和套接口</FONT><FONT SIZE=3>I/O</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>完成例程。</P>
<P ALIGN="JUSTIFY"> </P>
</FONT><B><FONT FACE="黑體" LANG="ZH-CN" SIZE=4><P><A NAME="_Toc336792974"><A NAME="_Toc336793450"></FONT><FONT FACE="Arial" SIZE=4>6.5.2.1 </FONT><FONT FACE="黑體" LANG="ZH-CN" SIZE=4>阻塞并且等待完成指示。</A></A></P>
</B></FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3><P ALIGN="JUSTIFY">	應用程序可以使用</FONT><FONT SIZE=3>WSAWaitForMultipleEvents()</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>函數來選擇阻塞程序直到一個或多個事件對象被設置。在</FONT><FONT SIZE=3>Win16</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>實現中,這種方式將使用一個阻塞鉤子,就象在標準的阻塞套接口操作時一樣。在</FONT><FONT SIZE=3>Win32</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>實現中,進程或線程會被真正地阻塞。因為</FONT><FONT SIZE=3>Windows Sockets 2</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>事件對象被實現成</FONT><FONT SIZE=3>Win32</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>事件,所以</FONT><FONT SIZE=3>Win32</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>函數</FONT><FONT SIZE=3>WaitForMultipleObjects()</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>也可以使用。這在線程需要阻塞套接口和非套接口事件時將會非常有用處。</P>
<P ALIGN="JUSTIFY"> </P>
</FONT><B><FONT FACE="黑體" LANG="ZH-CN" SIZE=4><P><A NAME="_Toc336792975"><A NAME="_Toc336793451"></FONT><FONT FACE="Arial" SIZE=4>6.5.2.2 </FONT><FONT FACE="黑體" LANG="ZH-CN" SIZE=4>檢查完成指示</A></A></P>
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -