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

윈도우 소켓 ] connect() 함수의 타임아웃은 21초

by eteo 2023. 12. 25.

 

 

 

 

 

connect() 함수의 타임아웃

 

TCP connection은 3-way-handshake에 의해 이루어지는데 클라이언트는 SYN 패킷을 전송한 이후 SYN+ACK를 수신할 때까지 대기하게 된다.

 

이때,

  • 서버기기가 네트워크에 연결되어 있고 포트가 닫혀있는 경우 서버기기는 SYN+ACK 대신 RST 패킷을 보낼테니 클라이언트는 서버에 연결할 수 없다는 걸 RTT(Round Trip Time)만에 알 수 있다. 로컬네트워크에서 이 시간은 몇 밀리초이지만 인터넷에서는 그 이상이 될 수 있다.
  • 서버기기가 네트워크에 없는 경우 클라이언트는 응답을 받지 못한채 SYN 패킷 전송을 재시도할 것이다. 이 때 재시도 횟수와 타임아웃은 운영체제의 TCP/IP protocol stack 설정값에 따라 달라질 수 있는데 윈도우의 경우 21초이다.

 

 

 

 

https://stackoverflow.com/questions/26896414/where-does-the-socket-timeout-of-21000-ms-come-from

 

Where does the socket timeout of 21000 ms come from?

The Problem An app I'm maintaining keeps getting socket timeouts after approximately 21000 ms, despite the fact that I've explicitly set longer timeouts. This seemingly magical value of 21000 ms ...

stackoverflow.com

 

 

 

테스트

#include <iostream>
#include <winsock2.h>
#include <windows.h>

#pragma comment(lib, "ws2_32.lib")

int main() {
    // Winsock 초기화
    WSADATA wsaData;
    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
        std::cerr << "Failed to initialize Winsock." << std::endl;
        return 1;
    }

    // 소켓 생성
    SOCKET socketDescriptor = socket(AF_INET, SOCK_STREAM, 0);
    if (socketDescriptor == INVALID_SOCKET) {
        std::cerr << "Failed to create socket." << std::endl;
        WSACleanup();
        return 1;
    }

    // 연결 시도할 서버 정보 설정
    sockaddr_in serverAddress;
    serverAddress.sin_family = AF_INET;
    serverAddress.sin_port = htons(80);
    serverAddress.sin_addr.s_addr = inet_addr("192.168.0.123");

    // 연결 시도 시작 시간 기록
    DWORD startTime = GetTickCount();
    DWORD elapsedTime;

    // TCP 연결 시도
    if (connect(socketDescriptor, (struct sockaddr*)&serverAddress, sizeof(serverAddress)) == SOCKET_ERROR) {
        // 연결 실패
        elapsedTime = GetTickCount() - startTime;
        std::cout << "Connection failed or timed out. Elapsed time: " << elapsedTime << " ms." << std::endl;
    }
    else {
        // 연결 성공
        elapsedTime = GetTickCount() - startTime;
        std::cout << "Connection successful. Elapsed time: " << elapsedTime << " ms." << std::endl;
    }

    // 소켓 및 Winsock 정리
    closesocket(socketDescriptor);
    WSACleanup();

    return 0;
}

 

 

네트워크에 없는 IP로 connect() 함수 호출 시 항상 약 21초만에 실패를 리턴한다.

 

 

 

 

관련글 :

2023.09.30 - [프로그래밍/C] - 윈도우 소켓 ] connect 비동기로 처리하기