LPFN_CONNECTEX回呼函式 (mswsock.h)
ConnectEx 函式會建立與指定套接字的連線,並在建立連接后選擇性地傳送數據。 只有連線導向套接字才支援 ConnectEx 函式。
語法
LPFN_CONNECTEX LpfnConnectex;
BOOL LpfnConnectex(
[in] SOCKET s,
[in] const sockaddr *name,
[in] int namelen,
[in, optional] PVOID lpSendBuffer,
[in] DWORD dwSendDataLength,
[out] LPDWORD lpdwBytesSent,
[in] LPOVERLAPPED lpOverlapped
)
{...}
參數
[in] s
描述項,識別先前系結的未連接套接字。 如需詳細資訊,請參閱「備註」。
[in] name
的指標
sockaddr 結構,指定要連接的位址。 針對 IPv4,sockaddr 包含位址系列、目的地 IPv4 位址和目的地埠 的AF_INET 。 針對 IPv6,sockaddr 結構包含位址系列、目的地 IPv6 位址、目的地埠,以及可能包含其他 IPv6 流程和範圍標識碼資訊AF_INET6。
[in] namelen
name 參數所指向之 sockaddr 結構的長度,以位元組為單位。
[in, optional] lpSendBuffer
建立連接之後要傳送之緩衝區的指標。 這是選擇性參數。 如果在呼叫 ConnectEx之前啟用 TCP_FASTOPEN 選項,則在連線建立期間可能會傳送其中一些數據。
[in] dwSendDataLength
lpSendBuffer 參數所指向數據的長度,以位元組為單位。 當 lpSendBuffer 參數為 NULL 時,會忽略此參數。
[out] lpdwBytesSent
成功傳回時,此參數會指向 DWORD 值,指出建立連接之後所傳送的位元組數目。 傳送的位元組來自 lpSendBuffer 參數所指向的緩衝區。 當 lpSendBuffer 參數為 NULL 時,會忽略此參數。
[in] lpOverlapped
用來處理要求的 OVERLAPPED 結構。 必須指定 lpOverlapped 參數,而且不能是 NULL。
傳回值
成功時, ConnectEx 函式會傳回 TRUE。 失敗時,函式會傳回 FALSE。 使用 WSAGetLastError 函式取得擴充錯誤資訊。 如果對 WSAGetLastError 函式的呼叫傳回 ERROR_IO_PENDING,則作業已成功起始且正在進行中。 在這種情況下,當重疊的作業完成時,呼叫仍可能會失敗。
如果傳回的錯誤碼是 WSAECONNREFUSED、 WSAENETUNREACH 或 WSAETIMEDOUT,則應用程式可以呼叫 ConnectEx、 WSAConnect,或在相同的套接字上再次 連線 。
錯誤碼 | 描述 |
---|---|
在使用 ConnectEx 之前,必須先進行成功的 WSAStartup 函式呼叫。 | |
網路子系統失敗。 | |
套接字的本機位址已在使用中,且套接字未標示為允許使用 SO_REUSEADDR 的位址重複使用。 此錯誤通常會在系結作業期間發生,但如果系結函式是以通配符 (位址呼叫,INADDR_ANY或in6addr_any針對本機 IP 位址指定的) 呼叫系結函式,可能會延遲到 ConnectEx 函式呼叫為止。 特定IP位址必須以隱含方式系結 ConnectEx 函式。 | |
指定的套接字上正在進行非封鎖 連線、 WSAConnect 或 ConnectEx 函數調用。 | |
遠程位址不是有效的位址,例如ADDR_ANY (ConnectEx 函式僅支援連線導向套接字) 。 | |
指定之系列中的位址無法用於此通訊端。 | |
嘗試連線遭到拒絕。 | |
名稱、lpSendBuffer 或 lpOverlapped 參數不是使用者位址空間的有效部分,或 namelen 太小。 | |
參數 s 是未系結或接聽套接字。 | |
套接字已連線。 | |
此時無法透過此主機連接網路。 | |
已嘗試對無法連接的主機進行通訊端作業。 | |
沒有可用的緩衝區空間;套接字無法連線。 | |
描述項不是套接字。 | |
嘗試連線逾時而不建立連線。 |
備註
ConnectEx 函式會將數個套接字函式結合成單一 API/核心轉換。 當 ConnectEx 函式的呼叫成功完成時,會執行下列作業:
- 已建立新的連線。
- 建立連線之後,會傳送選擇性的數據區塊。
針對以 Windows Vista 和更新版本為目標的應用程式,請考慮使用 WSAConnectByList 或 WSAConnectByName 函式,大幅簡化用戶端應用程式設計。
ConnectEx 函式只能與連接導向套接字搭配使用。 傳入 s 參數的套接字必須以套接字類型建立,SOCK_STREAM、SOCK_RDM或SOCK_SEQPACKET。
lpSendBuffer 參數會指向建立連接之後要傳送的數據緩衝區。 dwSendDataLength 參數會指定要傳送之數據位元組的長度。 應用程式可以使用 ConnectEx,要求使用 ConnectEx 傳送大型數據緩衝區,就像可以使用 Send 和 WSASend 函式一樣。 但強烈建議開發人員使用 ConnectEx 在單一呼叫中傳送大型緩衝區,因為此作業會使用大量的系統記憶體資源,直到傳送整個緩衝區為止。
如果 ConnectEx 函式成功,則已建立連線,而 lpSendBuffer 參數所指向的所有數據都會傳送至 name 參數所指向之 sockaddr 結構中指定的位址。
ConnectEx 函式使用重疊的 I/O。 因此, ConnectEx 函式可讓應用程式服務大量的用戶端,且線程相對較少。 相反地, WSAConnect 函式不會使用重疊的 I/O,通常需要在同時收到要求時,個別線程來服務每個連線要求。
連線導向套接字通常無法立即完成其連線,因此會起始作業,而且函式會立即以ERROR_IO_PENDING或WSA_IO_PENDING錯誤傳回。 當連線作業完成並達到成功或失敗時,會使用 lpOverlapped 中所指出的完成通知機制來報告狀態。 如同所有重疊函數調用,您可以使用事件或完成埠作為完成通知機制。 GetQueuedCompletionStatus 或 GetOverlappedResult 或 WSAGetOverlappedResult 函數的 lpNumberOfBytesTransferred 參數表示要求中傳送的位元組數目。
當 ConnectEx 函式成功完成時,套接字句柄只能傳遞至下列函式:
如果在先前連線的套接字上呼叫 TransmitFile 函式,其中包含TF_DISCONNECT和TF_REUSE_SOCKET旗標,則指定的套接字會傳回至其未連線的狀態,但仍系結。 在這種情況下,套接字的句柄可以傳遞至其 參數中的 ConnectEx 函式,但套接字無法在 AcceptEx 函數調用中重複使用。 同樣地,使用 TransmitFile 函式重複使用的已接受套接字不能用於 ConnectEx 的呼叫中。 請注意,在重複使用的套接字的情況下, ConnectEx 會受限於基礎傳輸的行為。 例如,TCP 套接字可能會受限於 TCP TIME_WAIT狀態,導致 ConnectEx 呼叫延遲。
當 ConnectEx 函式傳回 TRUE 時,套接字 會 處於連線套接字的默認狀態。 在套接字上設定SO_UPDATE_CONNECT_CONTEXT之前,套接字不會啟用先前設定的屬性或選項。 使用 setockopt 函式來設定SO_UPDATE_CONNECT_CONTEXT選項。
例如:
//Need to #include <mswsock.h> for SO_UPDATE_CONNECT_CONTEXT
int iResult = 0;
iResult = setsockopt( s, SOL_SOCKET, SO_UPDATE_CONNECT_CONTEXT, NULL, 0 );
取得ockopt 函式可以搭配 SO_CONNECT_TIME 套接字選項使用,以檢查 ConnectEx 進行時是否已建立連線。 如果已建立連線,則傳遞至 getsockopt 函式之 optval 參數中傳回的值是套接字已連接的秒數。 如果套接字未連線,傳回 的 optval 參數會包含0xFFFFFFFF。 必須以這種方式檢查連線,以判斷是否已建立連線一段時間,而不傳送任何數據;在這種情況下,建議您終止這類連線。
例如:
//Need to #include <mswsock.h> for SO_CONNECT_TIME
int seconds;
int bytes = sizeof(seconds);
int iResult = 0;
iResult = getsockopt( s, SOL_SOCKET, SO_CONNECT_TIME,
(char *)&seconds, (PINT)&bytes );
if ( iResult != NO_ERROR ) {
printf( "getsockopt(SO_CONNECT_TIME) failed with error: %u\n",
WSAGetLastError() );
}
else {
if (seconds == 0xFFFFFFFF)
printf("Connection not established yet\n");
else
printf("Connection has been established %ld seconds\n",
seconds);
}
如果名稱參數中所指向之 sockaddr 結構的 address 參數全部為零,ConnectEx 會傳回錯誤 WSAEADDRNOTAVAIL。 任何嘗試重新連線使用中的連線都會失敗,並出現錯誤碼 WSAEISCONN。
因為任何原因而關閉連線的套接字時,建議捨棄套接字並建立新的套接字。 這是因為基於任何原因,假設當連線套接字上發生問題時,應用程式必須捨棄套接字,並再次建立所需的套接字,才能返回穩定點。
如果使用 TF_REUSE_SOCKET 旗標呼叫 DisconnectEx 函式,則指定的套接字會傳回未連線的狀態,但仍系結。 在這種情況下,套接字的句柄可以傳遞至其 s 參數中的 ConnectEx 函式。
TCP 釋放關閉連線並重複使用其資源的時間間隔,稱為TIME_WAIT狀態或 2MSL 狀態。 在這段期間,相較於建立新的連線,可以重新開啟連線的成本比建立新的連線還要少。
TIME_WAIT行為是在 RFC 793 中指定,這需要 TCP 至少在網路 (MSL) 兩倍的間隔內維護封閉式連線。 當連線釋放時,其套接字組和用於套接字的內部資源可用來支援另一個連線。
Windows TCP 會在連線關閉之後還原為TIME_WAIT狀態。 處於TIME_WAIT狀態時,無法重複使用套接字組。 TIME_WAIT期間可藉由修改下列 DWORD 登錄設定來設定,以秒為單位表示TIME_WAIT期間。
\ HKEY_LOCAL_MACHINE系統\CurrentControlSet\服務\TCPIP\參數\TcpTimedWaitDelay
根據預設,MSL 會定義為120秒。 TcpTimedWaitDelay 登錄設定預設為值 240 秒,代表 120 秒或 4 分鐘的最大區段存留期 2 倍。 不過,您可以使用這個項目來自定義間隔。
減少這個專案的值可讓 TCP 更快釋放關閉的連線,為新的連線提供更多資源。 不過,如果此值太低,TCP 可能會在聯機完成之前釋放連線資源,要求伺服器使用其他資源重新建立連線。
此登錄設定可以從 0 設定為 300 秒。
Windows Phone 8:Windows Phone 8 和更新版本上的 Windows Phone Store 應用程式支援此函式。
Windows 8.1和 Windows Server 2012 R2:Windows 市集應用程式支援 Windows 8.1、Windows Server 2012 R2 和更新版本。
規格需求
需求 | 值 |
---|---|
最低支援的用戶端 | Windows 8.1、Windows Vista [傳統型應用程式 |UWP 應用程式] |
最低支援的伺服器 | Windows Server 2003 [傳統型應用程式 |UWP 應用程式] |
目標平台 | Windows |
標頭 | mswsock.h |