WSPStartup 函式 (ws2spi.h)

WSPStartup 函式會起始使用用戶端 (SPI) 的 Windows Sockets 服務提供者介面。

語法

int WSPStartup(
  [in]  WORD                wVersionRequested,
  [out] LPWSPDATA           lpWSPData,
  [in]  LPWSAPROTOCOL_INFOW lpProtocolInfo,
  [in]  WSPUPCALLTABLE      UpcallTable,
  [out] LPWSPPROC_TABLE     lpProcTable
);

參數

[in] wVersionRequested

呼叫端可以使用的最高 Windows Sockets SPI 支援版本。 高序位元組會指定次要版本 (修訂) 號碼;低序位元組會指定主要版本號碼。

[out] lpWSPData

WSPDATA 數據結構的指標,可接收 Windows Sockets 服務提供者的相關信息。

[in] lpProtocolInfo

定義所需通訊協定特性 之WSAProtocol_Info 結構的指標。 當單一提供者 DLL 能夠具現化多個不同的服務提供者時,這特別有用。

[in] UpcallTable

WSPUpCallTable 結構中傳遞的 Winsock 2 DLL (Ws2_32.dll) (Ws2_32.dll) 傳送分派數據表。

[out] lpProcTable

SPI 函式指標數據表的指標。 此數據表會以 WSPProc_Table 結構的形式傳回。

傳回值

如果成功, WSPStartup 函式會傳回零。 否則,它會傳回下列其中一個錯誤碼。

錯誤碼 意義
WSASYSNOTREADY
網路子系統無法使用。 如果 Windows Sockets 實作目前無法運作,就會傳回此錯誤,因為它用來提供網路服務的基礎系統目前無法使用。
WSAVERNOTSUPPORTED
Winsock.dll 版本超出範圍。 如果此特定 Windows Sockets 服務提供者未提供要求的 Windows Sockets SPI 支援版本,就會傳回此錯誤。
WSAEINPROGRESS
封鎖的 Windows Sockets 1.1 作業正在進行中。
WSAEPROCLIM
已達到 Windows Sockets 實作支援的工作數目限制。
WSAEFAULT
lpWSPDatalpProcTable 參數無效。

備註

Windows Sockets 2 傳輸服務提供者是 DLL,其中包含用於服務提供者初始化函式的單一導出程式進入點 WSPStartup。 所有其他服務提供者函式都可透過傳遞至 WSPStartup 函式之 lpProcTable 參數中的服務提供者分派數據表,存取 Winsock 2 DLL。 服務提供者 DLL 只會視需要載入 WinSock 2 DLL 的記憶體,並在不再需要服務時卸除。

服務提供者介面也會定義數種情況,其中傳輸服務提供者會呼叫 Winsock 2 DLL () ,以取得 DLL 支援服務。 傳輸服務提供者會傳回傳遞至 WSPStartup 函式之 Winsock 2 DLL 之 Winsock 2 DLL 的 httpall 分派數據表。

WSPStartup 函式必須是每個進程 Windows Sockets SPI 用戶端所呼叫的第一個 Windows Sockets SPI 函式。 它可讓用戶端指定所需的 Windows Sockets SPI 版本,並提供其快取分派表。 所有 (即,Windows Sockets 服務提供者所建立的 WPU) 前面加上 WPU 的函式,都會透過用戶端的) 分派表來叫用。 此函式也允許用戶端擷取特定 Windows Sockets 服務提供者實作的詳細數據。 Windows Sockets SPI 用戶端只能在成功叫用 WSPStartup 之後發出進一步的 Windows Sockets SPI 函式。 透過傳回WSPProc_Table結構的 lpProcTable 參數,擷取 SPI 函式其餘部分的指標數據表。

Winsock 2 DLL 會使用標準 Windows 動態連結庫載入機制,將服務提供者的介面 DLL 載入系統,並藉由呼叫 WSPStartup 函式加以初始化。 這通常是由呼叫 套接字WSASocket 函式的應用程式所觸發,以便建立與介面 DLL 目前未載入記憶體之服務提供者相關聯的新套接字。

為了支持未來版本的 Windows Sockets SPI 和 Ws2_32.dll,這可能與目前的 Windows Sockets SPI 有功能差異, 在 WSPStartup 中會進行交涉。 WSPStartup 的呼叫端 (Ws2_32.dll 或分層通訊協定) ,而 Windows Sockets 服務提供者會向彼此指出其可支援的最高 Windows 套接字版本,且每個都確認可接受另一個最高版本。 進入 WSPStartup 時,Windows Sockets 服務提供者會檢查用戶端所要求的版本。 如果此版本等於或高於服務提供者所支援的最低版本,則呼叫會成功,而服務提供者會在WSPDATA 結構的 wHighVersion 成員中傳回它所支援的最高版本,而且在 wVersion 成員中,其高版本和 wVersionRequested 參數中指定的版本下限。 然後,Windows Sockets 服務提供者會假設 Windows Sockets SPI 用戶端將使用 wVersion 成員中指定的 Windows Sockets 版本。 如果呼叫端無法接受 WSPDATA 結構的 wVersion 成員,它應該呼叫 LPWSPCleanup,並搜尋另一個 Windows Sockets 服務提供者或無法初始化。

此交涉可讓 Windows Sockets 服務提供者和 Windows Sockets SPI 用戶端支援各種 Windows Sockets 版本。 如果版本範圍有任何重疊,用戶端就可以成功利用 Windows Sockets 服務提供者。

Windows Sockets 規格的目前版本是 2.2 版。 目前的 Winsock DLL Ws2_32.dll支援要求下列任何 Windows Sockets 規格版本的應用程式:

  • 1.0
  • 1.1
  • 2.0
  • 2.1
  • 2.2

若要取得更高版本 Windows Sockets 規格之新語法的完整存取權,應用程式必須交涉此更高版本的語法。 在此情況下, wVersionRequested 參數應該設定為要求 2.2 版。 應用程式也必須完全符合該更高版本的 Windows Socket 規格,例如針對適當的頭文件進行編譯、與新連結庫連結或其他特殊案例。 Winsock 2 支援的 Winsock2.h 頭文件隨附於 Microsoft Windows 軟體開發套件 (SDK) 。

Windows Server 2008、Windows Vista、Windows Server 2003、Windows XP、Windows 2000 Windows NT 4.0 版支援 Service Pack 4 (SP4) 及更新版本、Windows Me、Windows 98 和 Windows 95 OSR2。 Windows Sockets 2.2 版也支援
具有 Windows Socket 2 Update 的 Windows 95。 這些平臺上的應用程式通常應該藉由設定 wVersionRequested 參數來要求 Winsock 2.2。

在 Windows 95 和 Windows NT 3.51 和更早版本上,Windows Sockets 1.1 版是支援的 Windows Sockets 規格最高版本。

撰寫的應用程式或 DLL 可以使用 Winsock DLL 所支援的較低版本 Windows Sockets 規格,以使用 WSPStartup 函式成功交涉此較低版本是合法且可行的。 例如,應用程式可以在具有 Winsock 2.2 DLL 的平台上傳遞至 WSPStartup 函式的 wVersionRequested 參數中要求 1.1 版。 在此情況下,應用程式應該只依賴符合所要求版本的功能。 不應該使用新的Ioctl程式代碼、現有函式的新行為,以及新的函式。 WSPStartup 所提供的版本交涉主要用來允許針對 Windows 95 開發的舊版 Winsock 1.1 應用程式,以及 Windows NT 3.51 和更早版本以相同行為在更新版本的 Windows 上執行。 Winsock 1.1 支援的 Winsock.h 頭文件隨附於 Windows SDK。

下圖提供 WSPStartup 如何搭配不同 WS2_32.DLL 和 Windows Sockets 服務提供者 (SP) 版本的範例。

DLL
 
versions
SP
 
versions
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 DLL 失敗
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.0 1.1 2.0 1.1 2.0 1.1 1.1 use 1.1
1.0 1.1 2.0 2.0 2.0 2.0 2.0 use 2.0
1.0 1.1 2.0 2.1 2.2 2.2 2.2 2.2 2.2 use 2.2
 

下列代碼段示範 Windows Sockets SPI 用戶端如何只支援第 2 版的 Windows Sockets SPI 進行 WSPStartup 呼叫:

WORD wVersionRequested;
WSPDATA WSPData;
 
int err;
 
WSPUPCALLTABLE upcallTable =
{ 
    /* initialize upcallTable with function pointers */
};
 
LPWSPPROC_TABLE lpProcTable =
{ 
    /* allocate memory for the ProcTable */
};
 
wVersionRequested = MAKEWORD( 2, 2 );
 
err = WSPStartup( wVersionRequested, &WSPData, lpProtocolBuffer, upcallTable, lpProcTable );
if ( err != 0 ) {
    /* Tell the user that we could not find a usable */
    /* Windows Sockets service provider.                     */
    return;
}
 
/* Confirm that the Windows Sockets service provider supports 2.2.*/
/* Note that if the service provider supports versions */
/* greater than 2.2 in addition to 2.2, it will still */
/* return 2.2 in wVersion since that is the version we  */
/* requested.                                           */
 
if ( LOBYTE( WSPData.wVersion ) != 2 ||
         HIBYTE( WSPData.wVersion ) != 2 ) {
    /* Tell the user that we could not find a usable */
    /* Windows Sockets service provider.                     */
    LPWSPCleanup( );
    return;   
}
 
/* The Windows Sockets service provider is acceptable. Proceed. */

此代碼段示範僅支援 2.2 版的 Windows Sockets 服務提供者如何執行 WSPStartup 交涉:

/* Make sure that the version requested is >= 2.2.  */
/* The low byte is the major version and the high   */
/* byte is the minor version.                       */
 
if ( (LOBYTE( wVersionRequested ) < 2) ||
     ((LOBYTE( wVersionRequested ) == 2) &&
     (HIBYTE( wVersionRequested ) < 2))) {
    return WSAVERNOTSUPPORTED;
}
 
/* Since we only support 2.2, set both wVersion and  */
/* wHighVersion to 2.2.                              */
 
lpWSPData->wVersion = MAKEWORD( 2, 2 );
lpWSPData->wHighVersion = MAKEWORD( 2, 2 );


一旦 Windows Sockets SPI 用戶端成功呼叫 WSPStartup ,就可以視需要繼續進行其他 Windows Sockets SPI 呼叫。 使用 Windows Sockets 服務提供者的服務完成時,客戶端必須呼叫 LPWSPCleanup ,才能讓 Windows Sockets 服務提供者釋放為用戶端配置的任何資源。

每個客戶端進程至少必須呼叫 一次 WSPStartup 函式,而且 Winsock 2 DLL 或其他實體可以多次呼叫。 每個成功的 WSPStartup 呼叫都必須呼叫相符的 LPWSPCleanup 函式。 服務提供者應該根據每個進程維護參考計數。 在每個 WSPStartup 呼叫上,呼叫端都可以指定服務提供者 DLL 支援的任何版本號碼。

服務提供者必須根據每個進程,將指標儲存為 WSPStartup 函式所接收做為其為其之其的 AzureAllTable 參數的用戶端之分派數據表。 如果指定的進程多次呼叫 WSPStartup ,服務提供者必須只使用最近提供的分派數據表指標。

如果 Windows Sockets SPI 用戶端需要多次取得 WSPDATA 結構資訊,則可以多次呼叫 WSPStartup。 在每個這類呼叫上,用戶端都可以指定提供者支援的任何版本號碼。

必須有一個 LPWSPCleanup 呼叫對應至每個成功的 WSPStartup 呼叫,以允許第三方 DLL 使用 Windows 套接字提供者。 例如,例如,如果 WSPStartup 呼叫三次, 則 LPWSPCleanup 的對應呼叫必須發生三次。 LPWSPCleanup 的前兩個呼叫除了遞減內部計數器以外,不會執行任何動作;最後的 LPWSPCleanup 呼叫會執行所有必要的資源解除分配。

如果用戶端是16位 Windows Sockets 1.1 用戶端,此函式 (和大部分其他服務提供者函式) 可以在以16位進程開頭的線程中叫用。 16 位進程的一個重要限制是16位進程無法建立線程。 這對規劃使用內部服務線程作為實作一部分的服務提供者實作者而言相當重要。

幸運的是,服務線程的條件通常只有兩個區域是強式的:

這兩個區域只能透過新的 Windows Sockets 2 函式存取,這隻能由 32 位進程叫用。

如果仔細遵循這兩個設計規則,則可以安全地使用服務線程:

  • 僅針對16位 Windows Sockets 1.1 用戶端無法使用的功能使用服務線程。
  • 僅視需要建立服務線程。

其他幾個注意事項也適用於使用內部服務線程。 首先,線程通常會有一些效能負面影響。 盡可能使用最少,並盡可能避免線程轉換。 其次,您的程式代碼應該一律檢查建立線程時是否有錯誤,並正常且有資訊地 (例如,使用 WSAEOPNOTSUPP) ,以防某些執行事件未預期會導致 16 位進程執行需要線程的程式代碼路徑。

分層服務提供者會提供此函式的實作,但它也是此函式呼叫 WSPStartup 以初始化通訊協定鏈結中下一層的用戶端。 呼叫下一層的 WSPStartup 可能會在執行此層的 WSPStartup 期間發生,或者可能會延遲並視需要呼叫,例如 呼叫 LPWSPSocket 時。 在任何情況下,某些特殊考慮適用於此函式的 lpProtocolInfo 參數,因為它會透過通訊協定鏈結的層級向下傳播。

分層提供者會搜尋 lpProtocolInfo 所參考結構的 ProtocolChain,藉由搜尋圖層本身的目錄專案標識元) 和鏈結中下一個專案的識別,來判斷鏈結中自己的位置 (。 如果下一個元素是另一層,則呼叫下一層的 WSPStartup 時,此層必須傳遞至下一層 lpProtocolInfo ,該層會參考具有相同未修改鏈結資訊的相同未修改 WSAProtocol_Info 結構。 不過,如果下一層是基底通訊協定 (,也就是鏈結中的最後一個專案) ,則呼叫基底提供者的 WSPStartup 時,此層會執行替代作業。 在此情況下,基底提供者 的WSAPROTOCOL_INFO 結構應該由 lpProtocolInfo 參數參考。

此原則的其中一個重要優點是基底服務提供者不需要注意通訊協定鏈結。

透過 LPWSPAddressToStringLPWSPDuplicateSocketLPWSPSocketLPWSPStringToAddress 等分層式來傳播WSAPROTOCOL_INFO結構時,適用相同的傳播原則。

規格需求

需求
最低支援的用戶端 Windows 2000 Professional [僅限傳統型應用程式]
最低支援的伺服器 Windows 2000 Server [僅限桌面應用程式]
目標平台 Windows
標頭 ws2spi.h

另請參閱

WSAProtocol_Info

LPWSPAddressToString

LPWSPStringToAddress

LPWSPCleanup

LPWSPDuplicateSocket

LPWSPEventSelect

WSPProc_Table

LPWSPSend

LPWSPSendTo

LPWSPSocket

WSPUpCallTable