編碼的世界 / 優質文選 / 財富

WSAStartup與WSACleanup


2021年7月04日
-   

WSAStartup與WSACleanup WSAStartup應該與WSACleanup成對使用,WSAStartup的功能是初始化Winsock DLL,WSACleanup是來解除與Socket庫的綁定並且釋放Socket庫所占用的系統資源。 在Windows下,Socket是以DLL的形式實現的。在DLL內部維持著一個計數器,只有第一次調用WSAStartup才真正裝載DLL,以後的 調用只是簡單的增加計數器,而WSACleanup函數的功能則剛好相反,每調用一次使計數器減1,當計數器減到0時,DLL就從內存中被卸載!因此,你 調用了多少次WSAStartup,就應相應的調用多少次的WSACleanup. WSAStartup()簡述: #include <winsock.h> int PASCAL FAR WSAStartup ( WORD wVersionRequested, LPWSADATA lpWSAData ); wVersionRequested Windows Sockets API提供的調用方可使用的最高版本號.高位字節指出副版本(修正)號,低位字節指明主版本號. lpWSAData 指向WSADATA數據結構的指針,用來接收Windows Sockets實現的細節. 注釋: 本函數必須是應用程序或DLL調用的第一個Windows Sockets函數.它允許應用程序或DLL指明Windows Sockets API的版本號及獲得特定Windows Sockets實現的細節.應用程序或DLL只能在一次成功的WSAStartup()調用之後才能調用進一步的Windows Sockets API函數. 為支持日後可能和Windows Sockets 1.1有功能上差異的Windows Sockets實現及應用程序,在WSAStartup()中規定了一個協議.WSAStartup()的調用方和Windows Sockets DLL互相通知對方它們可以支持的最高版本,並且互相確認對方的最高版本是可接受的. 在WSAStartup()函數的入口,Windows Sockets DLL檢查了應用程序所需的版本.如果版本高於DLL支持的最低版本,則調用成功並且DLL在wHighVersion中返回它所支持的最高版本,在 wVersion中返回它的高版本和wVersionRequested中的較小者.然後Windows Sockets DLL就會假設應用程序將使用wVersion.如果WSDATA結構中的wVersion域對調用方來說不可接收, 它就應調用WSACleanup()函數並且要麼去另一個Windows Sockets DLL中搜索,要麼初始化失敗. 本協議允許Windows Sockets DLL和Windows Sockets應用程序共同支持一定範圍的Windows Sockets版本.如果版本範圍有重疊,應用程序就可以成功地使用Windows Sockets DLL.下列的圖表給出了WSAStartup()在不同的應用程序和Windows Sockets DLL版本中是如何工作的: 應用程序版本 DLL版本 wVersionRequested wVersion wHighVersion 最終結果 1.1                    1.1            1.1                                 1.1            1.1                      use 1.1 1.0 1.1 1.0 1.1 1.0 1.0 use 1.0 1.0 1.0 1.1 1.0 1.0 1.1 use 1.0 1.1 1.0 1.1 1.1 1.1 1.1 use 1.1 1.1 1.0 1.1 1.0 1.0 失敗 1.0 1.1 1.0 -- -- WSAVERNOTSUPPORTED 1.0 1.1 1.0 1.1 1.1 1.1 1.1 use 1.1 1.1 2.0 1.1 2.0 1.1 1.1 use 1.1 2.0 1.1 2.0 1.1 1.1 失敗 下列代碼段給出了只支持Windows Sockets 1.1版本的應用程序是如何進行WSAStartup()調用的: WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD( 1, 1 ); err = WSAStartup( wVersionRequested, &wsaData ); if ( err != 0 ) { /* Tell the user that we couldn't find a useable */ /* winsock.dll. */ return; } /* Confirm that the Windows Sockets DLL supports 1.1.*/ /* Note that if the DLL supports versions greater */ /* than 1.1 in addition to 1.1, it will still return */ /* 1.1 in wVersion since that is the version we */ /* requested. */ if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 ) { /* Tell the user that we couldn't find a useable */ /* winsock.dll. */ WSACleanup( ); return; } /* The Windows Sockets DLL is acceptable. Proceed. */ 下面的代碼段示例了只支持1.1版的Windows Sockets DLL是如何進行WSAStartup()協商的: /* Make sure that the version requested is >= 1.1. */ /* The low byte is the major version and the high */ /* byte is the minor version. */ if ( LOBYTE( wVersionRequested ) < 1 || ( LOBYTE( wVersionRequested ) == 1 && HIBYTE( wVersionRequested ) < 1 ) { return WSAVERNOTSUPPORTED; } /* Since we only support 1.1, set both wVersion and */ /* wHighVersion to 1.1. */ lpWsaData->wVersion = MAKEWORD( 1, 1 ); lpWsaData->wHighVersion = MAKEWORD( 1, 1 ); 一旦應用程序或DLL進行了一次成功的WSAStartup()調用,它就可以繼續進行其它所需的Windows Sockets API調用.當它完成了使用該Windows Sockets DLL的服務後,應用程序或DLL必須調用WSACleanup()以允許Windows Sockets DLL釋放任何該應用程序的資源. 實際的Windows Sockets實現細節在WSAData結構中描述如下: struct WSAData { WORD wVersion; WORD wHighVersion; char szDescription[WSADESCRIPTION_LEN+1]; char szSystemStatus[WSASYSSTATUS_LEN+1]; unsigned short iMaxSockets; unsigned short iMaxUdpDg; char FAR * lpVendorInfo; }; 該結構的成員為: 成員 用法 wVersion Windows Sockets DLL期待調用方使用的Windows Sockets規範的版本. wHighVersion DLL可支持的Windows Sockets規範的最高版本.通常它和wVersion相同. szDescription 一個null結尾的ASCII字串,Windows Sockets DLL將Windows Sockets實現的說明及廠商描述拷至該串.這段文本(長度最多256個字符)可能包含任何字符, 但廠家注意到不把控制和格式字符包含進去:該字串的最可能用法就是在狀態消息中顯示. szSystemStatus 一個null結尾的ASCII字串,Windows Sockets DLL將相關的狀態和配置信息拷至該串.Windows Sockets DLL只有在該信息對用戶或支撐人員有用時才會使用該域:它不應該被認為是szDescription域的擴展. iMaxSockets 一個進程可以打開的最大套接口數目.Windows Sockets的實現可以提供一個全局的套接口池給任何進程分配;也可以為每個進程分配套接口資源.該數字可反映出Windows Sockets DLL或網絡軟件是如何配置的.應用程序員可以使用該數字作為該Windows Sockets實現是否可以被應用程序使用的原始依據.例如,一個X Windows服務器可能在它啟動時檢查iMaxSockets:若它小於8,應用程序應顯示一條錯誤信息, 讓用戶重新配置網絡軟件.(這是szSystemStatus可能使用到的一種情況.)顯然,並不保證一個特定的應用程序可以實際分配到 iMaxSockets個套接口,因為可能有其它的Windows Sockets應用程序在使用. iMaxUdpDg 以字節表示的可由Windows Sockets應用程序發送或接收的最大UDP數據報的大小.如果應用程序沒有給出限制,iMaxUdpDg為0.在Berkeley套接口的許多實現 中,對於UDP數據報的導向有一個隱含的限制8192字節.Windows Sockets的實現可以在分配碎片重組緩沖區的基礎上給出界限.對於一般的Windows Sockets實現iMaxUdpDg的最小值為512.注意不考慮iMaxUdpDg的值,而試圖在網絡上發送一個大於最大傳輸單元(MTU)的廣播數 據報是不明智的.(Windows Sockets API沒有提供發現MTU的機制,但它必須不小於512字節.) lpVendorInfo 指向廠商規定數據結構的遠指針.該結構的定義(如果提供)超出了本規範的範圍. 應用程序或DLL若需要多次得到WSAData結構信息,就必須多次調用WSAStartup().然而,wVersionRequired參數假設在所 有調用WSAStartup()中都相同;也就是,應用程序或DLL不能在第一次調用WSAStartup()後改變Windows Sockets的版本號. 對應於每一次WSAStartup()調用必須有一個WSACleanup()調用,以使第三級(third-party)DLL可以利用和應用程序相關 的Windows Sockets DLL.這意味著,例如,如果應用程序調用了WSAStartup()三次,它就必須調用WSACleanup()三次.對WSACleanup()的前 兩次調用除了減少內置計數器以外不做任何事, 對任務的最後一次WSACleanup()調用為任務釋放了所有所需的資源. 返回值: 0 成功. 否則返回下列的錯誤代碼之一.注意通常依靠應用程序調用WSAGetLastError()機制獲得的錯誤代碼是不能使用的,因為Windows Sockets DLL可能沒有建立"上一錯誤"信息儲存的客戶數據區域. 關於Windows Sockets提供者的說明: 每一個Windows Sockets應用程序必須在進行其它Windows Sockets API調用前進行WSAStartup()調用.這樣,本函數就可以用於初始化的目的. 進一步的說明在WSACleanup()的說明中有討論. 錯誤代碼: WSASYSNOTREADY 指出網絡通信依賴的網絡子系統還沒有准備好. WSAVERNOTSUPPORTED 所需的Windows Sockets API的版本未由特定的Windows Sockets實現提供. WSAEINVAL 應用程序指出的Windows Sockets版本不被該DLL支持. 參見: send(), sendto(), WSACleanup()

熱門文章