WSAAsyncSelect 函式 (winsock.h)
[ WSAAsyncSelect 函式可用於需求一節中指定的操作系統。 它在後續版本中可能會變更或無法使用。 不使用 Select 樣式 I/O,請搭配 WinSock2 使用 重疊的 I/O 和事件物件 。
WSAAsyncSelect 函式會要求套接字網路事件的 Windows 訊息型通知。
語法
int WSAAsyncSelect(
[in] SOCKET s,
[in] HWND hWnd,
[in] u_int wMsg,
[in] long lEvent
);
參數
[in] s
描述項,識別需要事件通知的套接字。
[in] hWnd
句柄,識別在發生網路事件時將接收訊息的視窗。
[in] wMsg
發生網路事件時要接收的訊息。
[in] lEvent
位掩碼,指定應用程式感興趣的網路事件組合。
傳回值
如果 WSAAsyncSelect 函式成功,則傳回值為零,前提是應用程式在網路事件集中感興趣的宣告成功。 否則,會傳回SOCKET_ERROR值,而且可以呼叫 WSAGetLastError 來擷取特定的錯誤號碼。
錯誤碼 | 意義 |
---|---|
使用此函式之前,必須先進行成功的 WSAStartup 呼叫。 | |
網路子系統失敗。 | |
其中一個指定的參數無效,例如未參考現有視窗的視窗句柄,或指定的套接字處於無效的狀態。 | |
封鎖的 Windows Sockets 1.1 呼叫正在進行中,或者服務提供者仍在處理回呼函式。 | |
描述項不是套接字。 |
當應用程式視窗收到訊息時,可以設定其他錯誤碼。 此錯誤碼是使用 WSAGETSELECTERROR 宏從回復訊息中的 lParam 擷取。 下表列出每個網路事件的可能錯誤碼。
事件:FD_CONNECT
錯誤碼 | 意義 |
---|---|
WSAEAFNOSUPPORT | 指定之系列中的位址無法用於此通訊端。 |
WSAECONNREFUSED | 嘗試連線遭到拒絕。 |
WSAENETUNREACH | 此時無法透過此主機連接網路。 |
WSAEFAULT | namelen 參數無效。 |
WSAEINVAL | 套接字已經系結至位址。 |
WSAEISCONN | 套接字已連線。 |
WSAEMFILE | 沒有更多檔案描述項可用。 |
WSAENOBUFS | 沒有可用的緩衝區空間。 套接字無法連接。 |
WSAENOTCONN | 未連接此通訊端。 |
WSAETIMEDOUT | 嘗試連線逾時而不建立連線。 |
事件:FD_CLOSE
錯誤碼 | 意義 |
---|---|
WSAENETDOWN | 網路子系統失敗。 |
WSAECONNRESET | 線上已由遠端重設。 |
WSAECONNABORTED | 線上因逾時或其他失敗而終止。 |
錯誤碼 | 意義 |
---|---|
WSAENETDOWN | 網路子系統失敗。 |
事件:FD_ROUTING_INTERFACE_CHANGE
錯誤碼 | 意義 |
---|---|
WSAENETUNREACH | 指定的目的地已無法再連線。 |
WSAENETDOWN | 網路子系統失敗。 |
備註
WSAAsyncSelect 函式用來要求 WS2_32.DLL 在偵測 lEvent 參數所指定的任何網路事件時,應該將訊息傳送至視窗 hWnd。 應該傳送的訊息是由 wMsg 參數所指定。 s 參數會 識別需要通知的套接字。
不論 lEvent 的值為何,WSAAsyncSelect 函式會自動將套接字設定為非封鎖模式。 若要 將套接字設定 回封鎖模式, 必須先透過呼叫WSAAAsyncSelect 將 lEvent 設為零來清除與套接字相關聯的事件記錄。 然後,您可以呼叫 ioctlsocket 或 WSAIoctl ,將套接字設定回封鎖模式。 如需如何將非封鎖套接字設定回封鎖模式的詳細資訊,請參閱 ioctlsocket 和 WSAIoctl 函式。
lEvent 參數是使用位 OR 運算子與下表所列的任何值來建構。
值 | 意義 |
---|---|
FD_READ | 設定為接收讀取整備的通知。 |
FD_WRITE | 想要接收整備的寫入通知。 |
FD_OOB | 想要接收 OOB 資料的抵達通知。 |
FD_ACCEPT | 想要接收連入連線的通知。 |
FD_CONNECT | 想要接收已完成連線或多點聯結作業的通知。 |
FD_CLOSE | 想要接收套接字關閉的通知。 |
FD_QOS | 想要收到套接字服務品質 (QoS) 變更的通知。 |
FD_GROUP_QOS | 想要接收套接字群組服務品質的通知, (QoS) 變更 (保留給未來與套接字群組搭配使用) 。 保留的。 |
FD_ROUTING_INTERFACE_CHANGE | 想要接收指定目的地 () 路由介面變更的通知。 |
FD_ADDRESS_LIST_CHANGE | 想要接收套接字通訊協定系列之本機通訊清單變更的通知。 |
發出 套接字的 WSAAsyncSelect 會取消相同套接字的任何先前 WSAAsyncSelect 或 WSAEventSelect 。 例如,若要同時接收讀取和寫入的通知,應用程式必須呼叫 WSAAsyncSelect 與 FD_READ 和 FD_WRITE,如下所示:
rc = WSAAsyncSelect(s, hWnd, wMsg, FD_READ|FD_WRITE);
無法為不同的事件指定不同的訊息。 下列程式代碼將無法運作;第二個呼叫會取消第一個呼叫的效果,而且只會回報訊息 wMsg2 的 FD_WRITE 事件:
rc = WSAAsyncSelect(s, hWnd, wMsg1, FD_READ);
rc = WSAAsyncSelect(s, hWnd, wMsg2, FD_WRITE);
若要取消所有通知,表示 Windows 套接字應該不會傳送與套接字上網路事件相關的進一步訊息, lEvent 會設定為零。
rc = WSAAsyncSelect(s, hWnd, 0, 0);
雖然 WSAAsyncSelect 會立即停用此實例中套接字的事件訊息張貼,但訊息可能會在應用程式消息佇列中等候。 因此,即使取消之後,應用程式也必須準備好接收網路事件訊息。 關閉具有 closesocket 的套接字也會取消 WSAAsyncSelect 訊息傳送,但佇列中的訊息仍適用相同的警告。
accept 函式所建立的套接字具有與用來接受它的接聽套接字相同的屬性。 因此,針對接聽套接字設定的 WSAAsyncSelect 事件也適用於已接受的套接字。 例如,如果接聽套接字具有 WSAAsyncSelect 事件FD_ACCEPT、FD_READ和FD_WRITE,則該接聽套接字上接受的任何套接字也會有用於訊息的相同 wMsg 值FD_ACCEPT、FD_READ和FD_WRITE事件。 如果需要不同的 wMsg 或事件,應用程式應該呼叫 WSAAsyncSelect,並傳遞接受的套接字和所需的新數據。
當 指定的套接字上發生其中一個指定的網路事件時,應用程式視窗 hWnd 會接收 訊息 wMsg。 wParam 參數會識別發生網路事件的套接字。 lParam 的低字會指定已發生的網路事件。 lParam 的高字組包含任何錯誤碼。 錯誤碼是 Winsock2.h 中所定義的任何錯誤。
#include <windows.h>
#define WSAGETSELECTEVENT(lParam) LOWORD(lParam)
#define WSAGETSELECTERROR(lParam) HIWORD(lParam)
使用這些宏會將應用程式的原始程式碼可移植性最大化。
下表列出可傳回的可能網路事件代碼。
值 | 意義 |
---|---|
FD_READ | 套接字已準備好讀取。 |
FD_WRITE | 套接字已準備好寫入。 |
FD_OOB | OOB 數據已準備好在套接字上讀取 |
FD_ACCEPT | 套接字已準備好接受新的連入連線。 |
FD_CONNECT | 在套接字完成時起始的連接或多點聯結作業。 |
FD_CLOSE | 套接字所識別 的連接 已關閉。 |
FD_QOS | 與 套接字相關聯的 服務品質已變更。 |
FD_GROUP_QOS | 保留的。 與 所屬套接字 群組相關聯的服務品質已變更 (保留給未來與套接字群組搭配使用) 。 |
FD_ROUTING_INTERFACE_CHANGE | 應該用來傳送至指定目的地的本機介面已變更。 |
FD_ADDRESS_LIST_CHANGE | 應用程式用戶端可系結的套接字通訊協定系列位址清單已變更。 |
雖然 WSAAsyncSelect 可以在多個事件中呼叫,但應用程式視窗會針對每個網路事件收到單一訊息。
如同 select 函式的情況, WSAAsyncSelect 經常用來判斷 傳送或 重新傳送或 重新 傳送) 的數據傳輸 (作業何時可以發出,並預期立即成功。 不過,強固的應用程式必須準備好接收訊息,並發出立即傳回 WSAEWOULDBLOCK 的 Windows Sockets 2 呼叫。 例如,可以執行下列事件順序:
- 數據抵達套接字 s;Windows Sockets 2 張貼 WSAAsyncSelect 訊息
- 應用程式會處理一些其他訊息
- 處理時,應用程式會發出
ioctlsocket(s, FIONREAD...)
,並注意到已準備好讀取數據 - 應用程式發出
recv(s,...)
讀取數據的 - 應用程式循環來處理下一則訊息,最後到達 WSAAsyncSelect 訊息,指出數據已準備好讀取
- 應用程式問題
recv(s,...)
,失敗並出現 WSAEWOULDBLOCK 錯誤。
WS2_32.DLL 不會持續向應用程式填入特定網路事件的訊息。 成功將特定事件的通知張貼至應用程式視窗,直到應用程式呼叫隱含重新啟用該網路事件的函式呼叫之前,該網路事件的進一步訊息 () 才會張貼到應用程式視窗。
事件 | 重新啟用函式 |
---|---|
FD_READ | recv、 recvrom、 WSARecv 或 WSARecvFrom。 |
FD_WRITE | sendto、 sendto、 WSASend 或 WSASendTo。 |
FD_OOB | recv、 recvrom、 WSARecv 或 WSARecvFrom。 |
FD_ACCEPT | 接受 或 WSAAccept ,除非 錯誤碼WSATRY_AGAIN 指出條件函式傳回CF_DEFER。 |
FD_CONNECT | 無。 |
FD_CLOSE | 無。 |
FD_QOS | WSAIoctl 搭配命令SIO_GET_QOS。 |
FD_GROUP_QOS | 保留的。 WSAIoctl 搭配命令SIO_GET_GROUP_QOS (保留供日后与套接字群组搭配使用) 。 |
FD_ROUTING_INTERFACE_CHANGE | WSAIoctl 搭配命令SIO_ROUTING_INTERFACE_CHANGE。 |
FD_ADDRESS_LIST_CHANGE | WSAIoctl 搭配命令SIO_ADDRESS_LIST_CHANGE。 |
任何重新啟用例程的呼叫,即使是失敗的例程,都會導致重新叫用相關事件的訊息張貼。
針對 FD_READ、 FD_OOB和 FD_ACCEPT 事件,會觸發訊息張貼。 這表示,如果呼叫重新啟用例程,而且在呼叫之後仍符合相關條件, 則會將 WSAAsyncSelect 訊息張貼至應用程式。 這可讓應用程式成為事件驅動,且不擔心任何時間抵達的數據量。 考量以下發生順序:
- 網路傳輸堆疊 會在套接字上 接收 100 個字節的數據,並導致 Windows Socket 2 張貼 FD_READ 訊息。
- 應用程式會發出 recv ( s、 buffptr、50、0) 以讀取 50 個字節。
- 因為仍有要讀取的數據,所以會張貼另一 個FD_READ 訊息。
FD_QOS和FD_GROUP_QOS事件會被視為觸發邊緣。 發生服務質量變更時,只會張貼一次訊息。 除非提供者偵測到服務品質的進一步變更,或應用程式重新交涉套接字的服務質量,否則將不會進行進一步的訊息。
FD_ROUTING_INTERFACE_CHANGE訊息會在發出這類 IOCTL 之後,用來連線 WSAIoctl 中指定的目的地時,會張貼SIO_ROUTING_INTERFACE_CHANGE訊息。
當發出WSAIoctl 與 SIO_ADDRESS_LIST_CHANGE 之後,應用程式可系結變更的位址清單時,就會張貼FD_ADDRESS_LIST_CHANGE訊息。
如果應用程式呼叫 WSAAsyncSelect 或呼叫重新叫用函式時發生任何事件,則會適當地張貼訊息。 例如,您可以參考以下兩個序列:
- 應用程式會呼叫 接聽。
- 已收到連線要求,但尚未接受。
- 應用程式會呼叫 WSAAsyncSelect ,指定它需要接收 套接字的FD_ACCEPT 訊息。 由於事件的持續性,Windows Sockets 2 會立即張貼 FD_ACCEPT 訊息。
FD_WRITE事件處理方式稍有不同。 當套接字第一次與 connect 或 WSAConnect (連線時,會在FD_CONNECT之後張貼FD_WRITE訊息,如果同時註冊 ) 或接受接受或接受 WSAAccept,然後在傳送作業失敗且 WSAEWOULDBLOCK 和緩衝區空間變成可用之後。 因此,應用程式可以假設從第一個 FD_WRITE 訊息開始傳送,直到傳送傳回 WSAEWOULDBLOCK 為止。 在這類失敗之後,應用程式會收到通知,以使用 FD_WRITE 訊息再次傳送。
只有在套接字設定為個別接收 OOB 數據時,才會使用 FD_OOB 事件。 如果套接字設定為內嵌接收 OOB 數據,則會將 OOB (加速) 數據視為一般數據,而且應用程式應該註冊感興趣的專案,而且會接收、 FD_READ 事件,而不是 FD_OOB 事件。 應用程式可以使用 setockopt 或 getsockopt 來設定或檢查要處理 OOB 資料的方式,以取得SO_OOBINLINE選項。
FD_CLOSE訊息中的錯誤碼指出套接字關閉是否正常或中止。 如果錯誤碼為零,則關閉正常;如果錯誤碼為 WSAECONNRESET,則套接字的虛擬線路已重設。 這隻適用於連線導向套接字,例如 SOCK_STREAM。
收到對應至套接字之虛擬線路的關閉指示時,就會張貼 FD_CLOSE 訊息。 在 TCP 詞彙中,這表示當連線進入 TIME WAIT 或 CLOSE WAIT 狀態時,就會張貼 FD_CLOSE 。 這會導致遠端端在傳送端或 closesocket 上執行關機。 只有在 從套接字讀取所有數據之後,才應該張貼FD_CLOSE,但應用程式應該在收到 FD_CLOSE 時檢查剩餘的數據,以避免遺失數據。
請注意,應用程式只會收到 FD_CLOSE 訊息來表示虛擬線路關閉,而且只有在所有已接收的數據都已讀取時,才可正常關閉。 它不會收到 FD_READ 訊息來指出此條件。
當與套接字或所屬套接字群組相關聯的任何參數已分別變更時,就會張貼FD_QOS或FD_GROUP_QOS訊息。 應用程式應該使用 WSAIoctl 搭配命令SIO_GET_QOS或SIO_GET_GROUP_QOS,分別取得套接字或套接字群組所屬的目前服務品質。
FD_ROUTING_INTERFACE_CHANGE和FD_ADDRESS_LIST_CHANGE事件也會被視為觸發邊緣。 當應用程式要求通知之後,透過發出 WSAIoctl 並對應發出SIO_ROUTING_INTERFACE_CHANGE或SIO_ADDRESS_LIST_CHANGE來要求通知時,只會張貼一次訊息。 在應用程式重新發出 IOCTL 並偵測到另一個變更之前,將不會再進行進一步的訊息,因為已發出 IOCTL。
以下是每個異步通知訊息的事件和條件摘要。
- FD_READ:
- FD_WRITE:
- FD_OOB:只有在預設) (停用 setockopt SO_OOBINLINE 時才有效。
-
FD_ACCEPT:
- 呼叫 WSAAsyncSelect 時,如果有目前可用的連線要求可供接受。
- 當連線要求送達時,如果 FD_ACCEPT 尚未張貼。
- 在接受呼叫之後,如果有另一個連線要求可供接受。
-
FD_CONNECT:
- 呼叫 WSAAsyncSelect 時,如果目前已建立連線。
- 呼叫 連線 之後,建立連接時,即使 連接 會立即成功,如數據報套接字一般。
- 呼叫 WSAJoinLeaf 之後,聯結作業完成時。
- 連線之後,WSAConnect 或 WSAJoinLeaf 會以非封鎖、連線導向的套接字呼叫。 以 WSAEWOULDBLOCK 的特定錯誤傳回的初始作業,但網路作業會繼續進行。 當判斷結果時,作業最終是否成功, FD_CONNECT 發生。 客戶端應該檢查錯誤碼,以判斷結果是否成功或失敗。
-
FD_CLOSE:僅適用於連線導向套接字 (,例如,SOCK_STREAM)
- 呼叫 WSAAsyncSelect 時,如果已關閉套接字連線,則為 。
- 在遠端系統起始正常關閉之後,當目前沒有數據可接收 (請注意,如果已收到數據,而且在遠端系統起始正常關閉時等候讀取,則直到讀取所有擱置的數據) 之後,才會傳遞 FD_CLOSE 。
- 本機系統在關閉時起始正常 關閉 ,而遠端系統已回應「數據結束」通知 (例如 TCP FIN) ,但目前沒有數據可供接收。
- 例如,當遠端系統終止連線 (時,傳送的 TCP RST ) ,lParam 將包含 WSAECONNRESET 錯誤值。
注意FD_CLOSE 在呼叫 closesocket 之後不會張貼。
-
FD_QOS:
- 呼叫 WSAAsyncSelect 時,如果已變更與套接字相關聯的服務品質,則為 。
- 在呼叫具有 SIO_GET_QOS 的 WSAIoctl 之後,當服務質量變更時。
- FD_GROUP_QOS:保留。
-
FD_ROUTING_INTERFACE_CHANGE:
- 呼叫 WSAIoctl 並呼叫 SIO_ROUTING_INTERFACE_CHANGE 之後,當應該用來連線到 IOCTL 中所指定目的地的本機介面變更時。
-
FD_ADDRESS_LIST_CHANGE:
- 呼叫 WSAIoctl 並呼叫 SIO_ADDRESS_LIST_CHANGE 之後,當應用程式可以繫結變更的本機地址清單時。
規格需求
需求 | 值 |
---|---|
最低支援的用戶端 | Windows 2000 Professional [僅限傳統型應用程式] |
最低支援的伺服器 | Windows 2000 Server [僅限桌面應用程式] |
目標平台 | Windows |
標頭 | winsock.h (包含 Winsock2.h) |
程式庫 | Ws2_32.lib |
Dll | Ws2_32.dll |