LPFN_CONNECTEX 콜백 함수(mswsock.h)

ConnectEx 함수는 지정된 소켓에 대한 연결을 설정하고 연결이 설정되면 필요에 따라 데이터를 보냅니다. ConnectEx 함수는 연결 지향 소켓에서만 지원됩니다.

참고 이 함수는 Windows 소켓 사양에 대한 Microsoft 관련 확장입니다.

 

구문

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 주소, 대상 포트에 대한 AF_INET6 포함되며 추가 IPv6 흐름 및 scope ID 정보가 포함될 수 있습니다.

[in] namelen

name 매개 변수가 가리키는 sockaddr 구조체의 길이(바이트)입니다.

[in, optional] lpSendBuffer

연결이 설정된 후 전송할 버퍼에 대한 포인터입니다. 이 매개 변수는 선택적 요소입니다. ConnectEx가 호출되기 전에 s에서 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를 호출하거나 동일한 소켓에서 다시 연결할 수 있습니다.

오류 코드 Description
WSANOTINITIALISED
ConnectEx를 사용하기 전에 성공적인 WSAStartup 함수 호출이 발생해야 합니다.
WSAENETDOWN
네트워크 하위 시스템이 실패했습니다.
WSAEADDRINUSE
소켓의 로컬 주소가 이미 사용 중이며 SO_REUSEADDR 주소를 다시 사용할 수 있도록 소켓이 표시되지 않았습니다. 이 오류는 일반적으로 바인딩 작업 중에 발생하지만 로컬 IP 주소에 대해 지정된 와일드카드 주소(INADDR_ANY 또는 in6addr_any)를 사용하여 bind 함수를 호출한 경우 ConnectEx 함수 호출까지 오류가 지연될 수 있습니다. 특정 IP 주소는 ConnectEx 함수에 의해 암시적으로 바인딩되어야 합니다.
WSAEALREADY
비 차단 연결, WSAConnect 또는 ConnectEx 함수 호출이 지정된 소켓에서 진행 중입니다.
WSAEADDRNOTAVAIL
원격 주소는 ADDR_ANY 같은 유효한 주소가 아닙니다( ConnectEx 함수는 연결 지향 소켓에 대해서만 지원됨).
WSAEAFNOSUPPORT
지정된 패밀리의 주소는 이 소켓에서 사용할 수 없습니다.
WSAECONNREFUSED
연결 시도가 거부되었습니다.
WSAEFAULT
이름, lpSendBuffer 또는 lpOverlapped 매개 변수가 사용자 주소 공간의 유효한 부분이 아니거나 namelen이 너무 작습니다.
WSAEINVAL
매개 변수 언바운드 또는 수신 대기 소켓입니다.
WSAEISCONN
소켓이 이미 연결되어 있습니다.
WSAENETUNREACH
현재 이 호스트에서 네트워크에 연결할 수 없습니다.
WSAEHOSTUNREACH
연결할 수 없는 호스트로 소켓 작업을 시도했습니다.
WSAENOBUFS
버퍼 공간을 사용할 수 없습니다. 소켓을 연결할 수 없습니다.
WSAENOTSOCK
설명자가 소켓이 아닙니다.
WSAETIMEDOUT
연결을 설정하지 않고 연결 시도가 시간 초과되었습니다.

설명

ConnectEx 함수는 여러 소켓 함수를 단일 API/커널 전환으로 결합합니다. ConnectEx 함수에 대한 호출이 성공적으로 완료되면 다음 작업이 수행됩니다.

  • 새 연결이 설정됩니다.
  • 연결이 설정된 후 선택적 데이터 블록이 전송됩니다.

Windows Vista 이상을 대상으로 하는 애플리케이션의 경우 클라이언트 애플리케이션 디자인을 크게 간소화하는 WSAConnectByList 또는 WSAConnectByName 함수를 사용하는 것이 좋습니다.

ConnectEx 함수는 연결 지향 소켓에서만 사용할 수 있습니다. s 매개 변수에 전달된 소켓은 SOCK_STREAM, SOCK_RDM또는SOCK_SEQPACKET 소켓 형식으로 만들어야 합니다.

lpSendBuffer 매개 변수는 연결이 설정된 후 보낼 데이터 버퍼를 가리킵니다. dwSendDataLength 매개 변수는 보낼 이 데이터의 길이(바이트)를 지정합니다. 애플리케이션은 Send 및 WSASend 함수를 사용할 수 있는 것과 동일한 방식으로 ConnectEx를 사용하여 대량의 데이터 버퍼를 보내도록 요청할 수 있습니다. 그러나 이 작업은 전체 버퍼가 전송될 때까지 많은 양의 시스템 메모리 리소스를 사용하므로 개발자는 ConnectEx를 사용하여 단일 호출에서 거대한 버퍼를 보내지 않는 것이 좋습니다.

ConnectEx 함수가 성공하면 연결이 설정되고 lpSendBuffer 매개 변수가 가리키는 모든 데이터가 이름 매개 변수가 가리키는 sockaddr 구조에 지정된 주소로 전송됩니다.

참고ConnectEx 함수에 대한 함수 포인터는 지정된 SIO_GET_EXTENSION_FUNCTION_POINTER opcode를 사용하여 WSAIoctl 함수를 호출하여 런타임에 가져와야 합니다. WSAIoctl 함수에 전달된 입력 버퍼에는 값이 ConnectEx 확장 함수를 식별하는 GUID(Globally Unique Identifier)인 WSAID_CONNECTEX 포함되어야 합니다. 성공하면 WSAIoctl 함수에서 반환된 출력에 ConnectEx 함수에 대한 포인터가 포함됩니다. WSAID_CONNECTEX GUID는 Mswsock.h 헤더 파일에 정의되어 있습니다.
 

ConnectEx 함수는 겹치는 I/O를 사용합니다. 결과적으로 ConnectEx 함수를 사용하면 애플리케이션이 비교적 적은 스레드로 많은 수의 클라이언트를 서비스할 수 있습니다. 반면, 겹치는 I/O를 사용하지 않는 WSAConnect 함수는 일반적으로 동시 요청이 수신될 때 각 연결 요청을 서비스하기 위해 별도의 스레드가 필요합니다.

참고 지정된 스레드에서 시작한 모든 I/O는 해당 스레드가 종료될 때 취소됩니다. 겹치는 소켓의 경우 작업이 완료되기 전에 스레드가 닫히면 보류 중인 비동기 작업이 실패할 수 있습니다. 자세한 내용은 ExitThread 를 참조하세요.

 

연결 지향 소켓은 연결을 즉시 완료할 수 없는 경우가 많으므로 작업이 시작되고 함수가 ERROR_IO_PENDING 또는 WSA_IO_PENDING 오류와 함께 즉시 반환됩니다. 연결 작업이 완료되고 성공 또는 실패가 발생하면 lpOverlapped에 표시된 완료 알림 메커니즘을 사용하여 상태 보고됩니다. 겹치는 모든 함수 호출과 마찬가지로 이벤트 또는 완료 포트를 완료 알림 메커니즘으로 사용할 수 있습니다. GetQueuedCompletionStatus 또는 GetOverlappedResult 또는 WSAGetOverlappedResult 함수의 lpNumberOfBytesTransferred 매개 변수는 요청에 전송된 바이트 수를 나타냅니다.

ConnectEx 함수가 성공적으로 완료되면 소켓 핸들 s를 다음 함수에만 전달할 수 있습니다.

TF_DISCONNECT 플래그와 TF_REUSE_SOCKET 플래그가 모두 있는 이전에 연결된 소켓에서 TransmitFile 함수가 호출되면 지정된 소켓이 연결되지 않았지만 여전히 바인딩된 상태로 반환됩니다. 이러한 경우 소켓의 핸들을 해당 매개 변수의 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);
}

참고 소켓이 열리면 setsockopt 호출이 수행되고 sendto 호출이 수행되면 Windows Sockets는 암시적 바인딩 함수 호출을 수행합니다.
 

name 매개 변수에서 가리키는 sockaddr 구조체의 주소 매개 변수가 모두 0이면 ConnectExWSAEADDRNOTAVAIL 오류를 반환합니다. 활성 연결을 다시 연결하려는 시도는 오류 코드 WSAEISCONN으로 실패합니다.

어떤 이유로든 연결된 소켓이 닫힌 경우 소켓을 삭제하고 새 소켓을 만드는 것이 좋습니다. 이에 대한 추론은 어떤 이유로든 연결된 소켓에서 상황이 어지러울 때 애플리케이션이 소켓을 삭제하고 안정적인 지점으로 돌아가기 위해 필요한 소켓을 다시 만들어야 한다고 가정하는 것이 가장 안전하기 때문입니다.

DisconnectEx 함수가 TF_REUSE_SOCKET 플래그를 사용하여 호출되면 지정된 소켓이 연결되지 않았지만 여전히 바인딩된 상태로 반환됩니다. 이러한 경우 소켓의 핸들을 해당 매개 변수의 ConnectEx 함수에 전달할 수 있습니다.

TCP가 닫힌 연결을 해제하고 리소스를 재사용하기 전에 경과해야 하는 시간 간격을 TIME_WAIT 상태 또는 2MSL 상태라고 합니다. 이 시간 동안 새 연결을 설정하는 것보다 클라이언트 및 서버에 대한 훨씬 적은 비용으로 연결을 다시 열 수 있습니다.

TIME_WAIT 동작은 RFC 793에 지정되어 TCP가 네트워크의 최대 세그먼트 수명(MSL)의 두 배 이상인 간격 동안 닫힌 연결을 유지 관리해야 합니다. 연결이 해제되면 소켓에 사용되는 소켓 쌍 및 내부 리소스를 사용하여 다른 연결을 지원할 수 있습니다.

Windows TCP는 연결이 닫히고 TIME_WAIT 상태로 되돌아갑니다. TIME_WAIT 상태에서 소켓 쌍을 다시 사용할 수 없습니다. TIME_WAIT 기간은 TIME_WAIT 기간을 초 단위로 나타내는 다음 DWORD 레지스트리 설정을 수정하여 구성할 수 있습니다.

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 스토어 앱에서 지원됩니다.

Windows 8.1Windows Server 2012 R2: 이 함수는 Windows 8.1, Windows Server 2012 R2 이상에서 Windows 스토어 앱에서 지원됩니다.

요구 사항

요구 사항
지원되는 최소 클라이언트 Windows 8.1, Windows Vista [데스크톱 앱 | UWP 앱]
지원되는 최소 서버 Windows Server 2003 [데스크톱 앱 | UWP 앱]
대상 플랫폼 Windows
헤더 mswsock.h

추가 정보

AcceptEx

DisconnectEx

ExitThread

GetOverlappedResult

GetQueuedCompletionStatus

OVERLAPPED

ReadFile

전송파일

WSAConnect

WSAConnectByList

WSAConnectByName

WSAGetLastError

WSAIoctl

WSARecv

WSASend

WSAStartup

Winsock 함수

Winsock 참조

WriteFile

bind

closesocket

connect

getsockopt

Recv

send

Sendto

setsockopt

sockaddr