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旗標,則會將指定的通訊端傳回至未連線的狀態,但仍系結。 在這種情況下,通訊端的控制碼可以在其s參數中傳遞至ConnectEx函式,但通訊端無法在AcceptEx函式呼叫中重複使用。 同樣地,使用 TransmitFile 函式重複使用的已接受通訊端不能用於 ConnectEx的呼叫中。 請注意,在重複使用的通訊端的情況下, ConnectEx 會受限於基礎傳輸的行為。 例如,TCP 通訊端可能會受限於 TCP TIME_WAIT 狀態,導致 ConnectEx 呼叫延遲。
當 ConnectEx 函式傳回 TRUE時,通訊端 會 處於連線通訊端的預設狀態。 在通訊端上設定SO_UPDATE_CONNECT_CONTEXT 之前,通訊端 不會啟用先前設定的屬性或選項。 使用 setsockopt 函式來設定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 );
getsockopt函式可以與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);
}
如果name參數中所指向之 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 Windows Phone 8 和更新版本上的市集應用程式支援此函式。
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 |
另請參閱
意見反應
提交並檢視相關的意見反應