共用方式為


Windows Sockets 1.1 封鎖例程和 EINPROGRESS

將應用程式從 Berkeley Sockets 環境移植到 Windows 環境的其中一個主要問題涉及封鎖:也就是說,叫用函式,直到相關聯的作業完成才會傳回。 作業需要很長的時間才能完成時,就會發生問題:例如,recv 函式,這可能會封鎖直到從對等系統收到數據為止。 Berkeley Sockets 模型中的預設行為是讓套接字以封鎖模式運作,除非程式設計人員明確要求將作業視為非封鎖。 Windows Sockets 1.1 環境無法假設先佔式排程。 因此,強烈建議程式設計人員盡可能使用 Windows Sockets 1.1 的非封鎖(異步)作業。 由於這並非總是可能的,因此提供了下列所述的虛擬封鎖設施。

注意

Windows Sockets 2 只在先佔式 32 位作系統上執行,其中死結不是問題。 Windows Sockets 1.1 建議的程序設計作法在 Windows Sockets 2 中並非必要。

 

即使在封鎖套接字上,某些函式 系結getockopt,以及 getpeername 立即完成。 這些函式的封鎖和非封鎖作業之間沒有任何差異。 其他作業,如 recv,可以立即完成或任意時間完成,視各種運輸條件而定。 套用至封鎖套接字時,這些作業稱為封鎖作業。 下列函式可以封鎖:

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

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

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

在 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 例程,而不是 選取getXbyY 例程。

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