본문 바로가기
프로그래밍/C

윈도우 소켓 ] connect 비동기로 처리하기

by eteo 2023. 9. 30.

 

 

논블로킹 소켓으로 설정한 뒤 connect를 시도한다.

connect 함수의 리턴값이 SOCKET_ERROR인 경우, WSAGetLastError()로 오류를 확인하여 WSAEWOULDBLOCK 인 경우 현재 백그라운드에서 연결이 진행중임을 나타낸다.

writeSet에 소켓을 넣고 select 함수를 호출하여 타임아웃 시간 동안 write-ready 상태가 되는지 감지한다.

select() 함수는 오류가 발생한 경우 -1, 타임아웃인 경우 0 그리고 이벤트를 감지한 경우 감지한 소켓 수를 리턴한다.

 

// 논블로킹 모드로 설정
u_long nonBlockOpt = 1;
if (ioctlsocket(cSocket, FIONBIO, &nonBlockOpt) == SOCKET_ERROR) {
    OutputDebugString("ioctlsocket() error.\n");
    return false;
}

// 비동기 connect 시도
if (connect(cSocket, (SOCKADDR*)&servInfo, sizeof(servInfo)) == SOCKET_ERROR)
{
    // 비동기 connect 작업이 진행중이 아닌 경우
    if (WSAGetLastError() != WSAEWOULDBLOCK)
    {
        OutputDebugString("connect() error");
        return false;
    }
}

fd_set writeSet;
FD_ZERO(&writeSet);
FD_SET(cSocket, &writeSet);

struct timeval timeout;
timeout.tv_sec = 1;
timeout.tv_usec = 0;

// 1초 동안 연결 상태 모니터링
int result = select(0, NULL, &writeSet, NULL, &timeout);
if (result == SOCKET_ERROR)
{
    OutputDebugString("select() error\n");
    return false;
}
else if (result == 0)
{
    OutputDebugString("select() timeout\n");
    return false;
}
else if (!FD_ISSET(cSocket, &writeSet))
{
    OutputDebugString("Connection failed!\n");
    return false;
}