Windows Sockets 1.1 封鎖常式和 EINPROGRESS

將應用程式從通訊端環境移植到 Windows 環境的其中一個主要問題包括封鎖;也就是說,叫用在關聯作業完成之前不會傳回的函式。 作業需要很長的時間才能完成時,就會發生問題:範例是 recv 函式,在從對等系統收到資料之前可能會封鎖。 除非程式設計人員明確要求將作業視為非封鎖,否則 可讓通訊端在封鎖模式中運作,否則 可讓通訊端運作的預設行為。 Windows Sockets 1.1 環境無法假設先占式排程。 因此,強烈建議程式設計人員盡可能使用 Windows Sockets 1.1 時,使用非封鎖 (非同步) 作業。 由於這不一定可行,因此提供了下列所述的虛擬封鎖功能。

注意

Windows Sockets 2 只會在發生死結的先占式 32 位作業系統上執行,而死結並無問題。 Windows Sockets 1.1 中不建議使用 Windows Sockets 1.1 的程式設計做法。

 

即使在封鎖通訊端上,某些函式 — 系結getockoptgetpeername ,例如立即完成。 這些函式的封鎖和非封鎖作業之間沒有任何差異。 視各種傳輸條件而定,其他作業例如 recv可以立即完成,或花費任意時間完成。 套用至封鎖通訊端時,這些作業稱為封鎖作業。 下列函式可以封鎖:

使用 16 位 Windows Sockets 1.1 時,無法立即完成的封鎖作業會由虛擬封鎖處理,如下所示。

服務提供者會起始作業,然後輸入迴圈,它會在其中分派任何 Windows 訊息, (視需要將處理器提供給另一個執行緒,視需要) ,然後檢查 Windows Sockets 函式是否完成。 如果函式已完成,或已叫用 WSACancelBlockingCall ,則封鎖函式會以適當的結果完成。

服務提供者必須允許安裝不會處理訊息的封鎖攔截函式,以避免在封鎖作業未完成時重新進入訊息的可能性。 最簡單的封鎖攔截函式會傳回 FALSE。 如果 Windows Sockets DLL 相依于內部作業的訊息,它可以在執行應用程式封鎖勾點之前,先執行 PeekMessage (hMyWnd...) ,讓它可以取得其訊息,而不會影響系統的其餘部分。

在 16 位的 Windows Sockets 1.1 環境中,如果收到 Windows 訊息來處理正在進行封鎖作業的進程,則應用程式會嘗試發出另一個 Windows Sockets 呼叫的風險。 由於安全管理此條件的困難,Windows Sockets 1.1 不支援這類應用程式行為。 不允許應用程式進行一個以上的巢狀 Windows Sockets 函式呼叫。 特定工作只允許一個未完成的函式呼叫。 唯一的例外狀況是提供兩個函式來協助程式設計人員在此情況下: WSAIsBlockingWSACancelBlockingCall

您可以隨時呼叫 WSAIsBlocking 函式,以判斷是否正在進行封鎖的 Windows Sockets 1.1 呼叫。 同樣地,您可以隨時呼叫 WSACancelBlockingCall 函式來取消進行中的封鎖呼叫。 Windows Sockets 函式的任何其他巢狀都會失敗,並出現 WSAEINPROGRESS 錯誤。

請注意,這項限制同時適用于封鎖和非封鎖作業。 對於在呼叫 WSAStartup時交涉 2.0 版或更新版本的 Windows Sockets 2 應用程式,不會限制作業的巢狀作業結束。 在罕見的情況下,作業可能會變成巢狀,例如 在 WSAAccept 條件式接受回呼期間,或服務提供者接著叫用 Windows Sockets 2 函式。

雖然這個機制足以用於簡單的應用程式,但無法支援更進階應用程式的複雜訊息分派需求 (,例如使用 MDI 模型) 。 對於這類應用程式,Windows Sockets API 包含 WSASetBlockingHook函式,可讓應用程式指定可呼叫的特殊常式,而不是上述討論中所述的預設訊息分派常式。

只有在下列所有專案都成立時,Windows Sockets 提供者才會呼叫封鎖攔截:

  • 常式是定義為能夠封鎖的常式。
  • 指定的通訊端是封鎖通訊端。
  • 無法立即完成要求。

通訊端預設會設定為封鎖,但具有FIONBIO IOCTL 或WSAAsyncSelect函式的ioctlsocket函式可以將通訊端設定為非封鎖模式。

一律不會呼叫封鎖攔截,而且如果應用程式遵循下列指導方針,應用程式就不需要擔心重新進入問題,封鎖攔截可能會引入:

  • 它只會使用非封鎖通訊端。
  • 它會使用 WSAAsyncSelect 和/或 WSAAsyncGetXByY 常式,而不是 selectgetXbyY 常式。

如果 Windows Sockets 1.1 應用程式叫用非同步或非封鎖作業,該作業會取得記憶體物件的指標 (緩衝區或全域變數,例如) 做為引數,應用程式會負責確保整個作業中的 Windows Sockets 都可以使用物件。 應用程式不得叫用任何可能會影響所涉及記憶體對應或位址可用性的 Windows 函式。