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 來擷取特定的錯誤號碼。

錯誤碼 意義
WSANOTINITIALISED
使用此函式之前,必須先進行成功的 WSAStartup 呼叫。
WSAENETDOWN
網路子系統失敗。
WSAEINVAL
其中一個指定的參數無效,例如未參考現有視窗的視窗句柄,或指定的套接字處於無效的狀態。
WSAEINPROGRESS
封鎖的 Windows Sockets 1.1 呼叫正在進行中,或者服務提供者仍在處理回呼函式。
WSAENOTSOCK
描述項不是套接字。
 

當應用程式視窗收到訊息時,可以設定其他錯誤碼。 此錯誤碼是使用 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 函式會自動將套接字設定為非封鎖模式。 若要 將套接字設定 回封鎖模式, 必須先透過呼叫WSAAAsyncSelectlEvent 設為零來清除與套接字相關聯的事件記錄。 然後,您可以呼叫 ioctlsocketWSAIoctl ,將套接字設定回封鎖模式。 如需如何將非封鎖套接字設定回封鎖模式的詳細資訊,請參閱 ioctlsocketWSAIoctl 函式。

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 會取消相同套接字的任何先前 WSAAsyncSelectWSAEventSelect 。 例如,若要同時接收讀取和寫入的通知,應用程式必須呼叫 WSAAsyncSelectFD_READFD_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_ACCEPTFD_READFD_WRITE,則該接聽套接字上接受的任何套接字也會有用於訊息的相同 wMsgFD_ACCEPT、FD_READFD_WRITE事件。 如果需要不同的 wMsg 或事件,應用程式應該呼叫 WSAAsyncSelect,並傳遞接受的套接字和所需的新數據。

指定的套接字上發生其中一個指定的網路事件時,應用程式視窗 hWnd 會接收 訊息 wMsgwParam 參數會識別發生網路事件的套接字。 lParam 的低字會指定已發生的網路事件。 lParam 的高字組包含任何錯誤碼。 錯誤碼是 Winsock2.h 中所定義的任何錯誤。

注意 收到事件通知訊息時, WSAGetLastError 函式無法用來檢查錯誤值,因為傳回的錯誤值可能與 lParam 高字中的值不同。
 
您可以使用 Winsock2.h 中定義的宏 WSAGETSELECTERRORWSAGETSELECTEVENT,從 lParam 擷取錯誤和事件碼:
#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 呼叫。 例如,可以執行下列事件順序:

  1. 數據抵達套接字 s;Windows Sockets 2 張貼 WSAAsyncSelect 訊息
  2. 應用程式會處理一些其他訊息
  3. 處理時,應用程式會發出 ioctlsocket(s, FIONREAD...) ,並注意到已準備好讀取數據
  4. 應用程式發出 recv(s,...) 讀取數據的
  5. 應用程式循環來處理下一則訊息,最後到達 WSAAsyncSelect 訊息,指出數據已準備好讀取
  6. 應用程式問題 recv(s,...),失敗並出現 WSAEWOULDBLOCK 錯誤。
您也可以使用其他序列。

WS2_32.DLL 不會持續向應用程式填入特定網路事件的訊息。 成功將特定事件的通知張貼至應用程式視窗,直到應用程式呼叫隱含重新啟用該網路事件的函式呼叫之前,該網路事件的進一步訊息 () 才會張貼到應用程式視窗。

事件 重新啟用函式
FD_READ recvrecvromWSARecvWSARecvFrom
FD_WRITE sendtosendtoWSASendWSASendTo
FD_OOB recvrecvromWSARecvWSARecvFrom
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_READFD_OOBFD_ACCEPT 事件,會觸發訊息張貼。 這表示,如果呼叫重新啟用例程,而且在呼叫之後仍符合相關條件, 則會將 WSAAsyncSelect 訊息張貼至應用程式。 這可讓應用程式成為事件驅動,且不擔心任何時間抵達的數據量。 考量以下發生順序:

  1. 網路傳輸堆疊 會在套接字上 接收 100 個字節的數據,並導致 Windows Socket 2 張貼 FD_READ 訊息。
  2. 應用程式會發出 recv ( sbuffptr、50、0) 以讀取 50 個字節。
  3. 因為仍有要讀取的數據,所以會張貼另一 個FD_READ 訊息。
使用這些語意時,應用程式不需要讀取所有可用的數據,以回應FD_READ訊息—適當地回應每個FD_READ訊息的單一 recv。 如果應用程式發出多個 recv 呼叫以回應單一 FD_READ,它可以接收多個 FD_READ 訊息。 這類應用程式可能需要先停用FD_READ訊息,才能啟動 recv 呼叫,方法是呼叫未設定FD_READ事件 WSAsyncSelect

FD_QOSFD_GROUP_QOS事件會被視為觸發邊緣。 發生服務質量變更時,只會張貼一次訊息。 除非提供者偵測到服務品質的進一步變更,或應用程式重新交涉套接字的服務質量,否則將不會進行進一步的訊息。

FD_ROUTING_INTERFACE_CHANGE訊息會在發出這類 IOCTL 之後,用來連線 WSAIoctl 中指定的目的地時,會張貼SIO_ROUTING_INTERFACE_CHANGE訊息。

當發出WSAIoctl 與 SIO_ADDRESS_LIST_CHANGE 之後,應用程式可系結變更的位址清單時,就會張貼FD_ADDRESS_LIST_CHANGE訊息。

如果應用程式呼叫 WSAAsyncSelect 或呼叫重新叫用函式時發生任何事件,則會適當地張貼訊息。 例如,您可以參考以下兩個序列:

  1. 應用程式會呼叫 接聽
  2. 已收到連線要求,但尚未接受。
  3. 應用程式會呼叫 WSAAsyncSelect ,指定它需要接收 套接字的FD_ACCEPT 訊息。 由於事件的持續性,Windows Sockets 2 會立即張貼 FD_ACCEPT 訊息。

FD_WRITE事件處理方式稍有不同。 當套接字第一次與 connectWSAConnect (連線時,會在FD_CONNECT之後張貼FD_WRITE訊息,如果同時註冊 ) 或接受接受或接受 WSAAccept,然後在傳送作業失敗且 WSAEWOULDBLOCK 和緩衝區空間變成可用之後。 因此,應用程式可以假設從第一個 FD_WRITE 訊息開始傳送,直到傳送傳回 WSAEWOULDBLOCK 為止。 在這類失敗之後,應用程式會收到通知,以使用 FD_WRITE 訊息再次傳送。

只有在套接字設定為個別接收 OOB 數據時,才會使用 FD_OOB 事件。 如果套接字設定為內嵌接收 OOB 數據,則會將 OOB (加速) 數據視為一般數據,而且應用程式應該註冊感興趣的專案,而且會接收、 FD_READ 事件,而不是 FD_OOB 事件。 應用程式可以使用 setockoptgetsockopt 來設定或檢查要處理 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_QOSFD_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
    1. 呼叫 WSAAsyncSelect 時,如果有數據目前可供接收。
    2. 當數據送達時,如果 尚未張貼FD_READ
    3. 呼叫 recvrecvfrom 之後,如果數據仍可供接收,則具有或不含MSG_PEEK) 。
      注意 啟用 setockopt SO_OOBINLINE時,數據會同時包含上述實例中的一般數據和 OOB 數據。
       
  • FD_WRITE
    1. WSAAsyncSelect 呼叫時,如果可能 傳送sendto ,則為 。
    2. 線上接受呼叫之後,連線建立時。
    3. 當傳送sendto 失敗並出現 WSAEWOULDBLOCK 之後,當 sendsendto 可能成功時。
    4. 在無連線套接字上 系結 之後。 FD_WRITE 目前可能會發生 (實作相依) 。 在任何情況下,一律會在 系結 作業之後立即寫入無連線套接字。
  • FD_OOB:只有在預設) (停用 setockopt SO_OOBINLINE 時才有效。
    1. 呼叫 WSAAsyncSelect 時,如果有 OOB 數據目前可以使用 MSG_OOB 旗標接收。
    2. 當 OOB 數據送達時,如果 FD_OOB 尚未張貼。
    3. 在透過或不使用 MSG_OOB 旗標呼叫 recvrecvfrom 之後,如果 OOB 資料仍可供接收。
  • FD_ACCEPT
    1. 呼叫 WSAAsyncSelect 時,如果有目前可用的連線要求可供接受。
    2. 當連線要求送達時,如果 FD_ACCEPT 尚未張貼。
    3. 在接受呼叫之後,如果有另一個連線要求可供接受。
  • FD_CONNECT
    1. 呼叫 WSAAsyncSelect 時,如果目前已建立連線。
    2. 呼叫 連線 之後,建立連接時,即使 連接 會立即成功,如數據報套接字一般。
    3. 呼叫 WSAJoinLeaf 之後,聯結作業完成時。
    4. 連線之後,WSAConnectWSAJoinLeaf 會以非封鎖、連線導向的套接字呼叫。 以 WSAEWOULDBLOCK 的特定錯誤傳回的初始作業,但網路作業會繼續進行。 當判斷結果時,作業最終是否成功, FD_CONNECT 發生。 客戶端應該檢查錯誤碼,以判斷結果是否成功或失敗。
  • FD_CLOSE:僅適用於連線導向套接字 (,例如,SOCK_STREAM)
    1. 呼叫 WSAAsyncSelect 時,如果已關閉套接字連線,則為 。
    2. 在遠端系統起始正常關閉之後,當目前沒有數據可接收 (請注意,如果已收到數據,而且在遠端系統起始正常關閉時等候讀取,則直到讀取所有擱置的數據) 之後,才會傳遞 FD_CLOSE
    3. 本機系統在關閉時起始正常 關閉 ,而遠端系統已回應「數據結束」通知 (例如 TCP FIN) ,但目前沒有數據可供接收。
    4. 例如,當遠端系統終止連線 (時,傳送的 TCP RST ) ,lParam 將包含 WSAECONNRESET 錯誤值。
      注意FD_CLOSE 在呼叫 closesocket 之後不會張貼。
       
  • FD_QOS
    1. 呼叫 WSAAsyncSelect 時,如果已變更與套接字相關聯的服務品質,則為 。
    2. 在呼叫具有 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

另請參閱

WSAEventSelect

Winsock 函式

Winsock 參考

select