오류 코드 - errno, h_errno 및 WSAGetLastError

Winsock 애플리케이션에서는 Windows GetLastError 함수 대신 Windows 소켓인 WSAGetLastError 함수를 사용하여 오류 코드를 검색합니다. Windows 소켓에서 반환된 오류 코드는 UNIX 소켓 오류 코드 상수와 유사하지만 상수는 모두 WSA 접두사로 지정됩니다. 따라서 Winsock 애플리케이션에서는 WSAEWOULDBLOCK 오류 코드가 반환되고 UNIX 애플리케이션에서는 EWOULDBLOCK 오류 코드가 반환됩니다.

Windows 소켓에서 설정한 오류 코드는 errno 변수를 통해 사용할 수 없습니다. 또한 getXbyY 함수 클래스의 경우 h_errno 변수를 통해 오류 코드를 사용할 수 없습니다. WSAGetLastError 함수는 다중 스레드 프로세스의 스레드가 스레드당 오류 정보를 얻을 수 있는 신뢰할 수 있는 방법을 제공하기 위한 것입니다.

BSD(Berkeley UNIX)와의 호환성을 위해 초기 버전의 Windows(Windows 소켓 2 업데이트 및 Windows 98을 사용하는 Windows 95)는 일반적으로 BSD의 errno.h 에 있는 일반 버클리 오류 상수를 해당하는 Windows 소켓 WSA 오류로 다시 정의했습니다. 예를 들어 ECONNREFUSED는 Winsock.h 헤더 파일에서 WSAECONNREFUSED로 정의되었습니다. 이후 버전의 Windows(Windows NT 3.1 이상)에서 이러한 정의는 Microsoft C/C++ 및 Visual Studio에서 사용되는 errno.h와의 충돌을 방지하기 위해 주석 처리되었습니다.

Microsoft SDK(Windows 소프트웨어 개발 키트), SDK(플랫폼 소프트웨어 개발 키트) 및 Visual Studio에 포함된 Winsock2.h 헤더 파일에는 BSD 소켓 오류 코드를 WSA 오류 상수와 동일하게 정의하는 #ifdef 0 및 #endif 블록 내에서 정의의 주석 처리된 블록이 여전히 포함되어 있습니다. UNIX, BSD 및 Linux 소켓 프로그래밍과의 호환성을 제공하는 데 사용할 수 있습니다. BSD와의 호환성을 위해 애플리케이션에서 Winsock2.h 를 변경하고 이 블록의 주석 처리를 해제하도록 선택할 수 있습니다. 그러나 애플리케이션 개발자는 대부분의 애플리케이션에서 errno.h 와의 불가피한 충돌로 인해 이 블록의 주석 처리를 해제하지 않는 것이 좋습니다. 또한 BSD 소켓 오류는 UNIX, BSD 및 Linux 프로그램에서 사용되는 값과 매우 다른 값으로 정의됩니다. 애플리케이션 개발자는 소켓 애플리케이션에서 WSA 오류 상수를 사용하는 것이 좋습니다.

이러한 정의는 #ifdef 0 및 #endif 블록 내에서 Winsock2.h 헤더에 주석 처리된 상태로 유지됩니다. 애플리케이션 개발자가 호환성을 위해 BSD 오류 코드를 사용해야 하는 경우 애플리케이션에서 양식 줄을 포함하도록 선택할 수 있습니다.

#include <windows.h>

#define errno WSAGetLastError()

이렇게 하면 전역 errno 를 사용하도록 작성된 네트워킹 코드가 단일 스레드 환경에서 올바르게 작동할 수 있습니다. 몇 가지 매우 심각한 단점이 있습니다. 소스 파일에 소켓 및 비 소켓 함수 모두에 대해 errno 를 검사하는 코드가 포함된 경우 이 메커니즘을 사용할 수 없습니다. 또한 애플리케이션에서 errno에 새 값을 할당할 수 없습니다. (Windows 소켓에서는 이 용도로 WSASetLastError 함수를 사용할 수 있습니다.)

일반적인 BSD 스타일

r = recv(...);
if (r == -1
    && errno == EWOULDBLOCK)
    {...}

기본 스타일

r = recv(...);
if (r == -1       /* (but see below) */
    && WSAGetLastError() == EWOULDBLOCK)
    {...}

호환성을 위해 Berkeley Sockets 4.3과 일치하는 오류 상수가 제공되지만 애플리케이션은 WSA 오류 코드 정의를 사용하는 것이 좋습니다. 특정 Windows 소켓 함수에서 반환되는 오류 코드는 Microsoft C©에서 정의한 대로 표준 오류 코드 범위에 속하기 때문입니다. 따라서 이전 소스 코드 조각의 더 나은 버전은 다음과 같습니다.

r = recv(...);
if (r == -1       /* (but see below) */
    && WSAGetLastError() == WSAEWOULDBLOCK)
    {...}

1995년에 정의된 원래 Winsock 1.1 사양은 오류 코드 집합을 권장하고 각 함수의 결과로 반환될 수 있는 가능한 오류를 나열했습니다. Windows Sockets 2에는 원래 Winsock 사양에 나열된 기능 외에도 반환된 다른 Windows 소켓 오류 코드와 함께 함수 및 기능이 추가되었습니다. 시간이 지남에 따라 개발자가 사용할 Winsock을 향상시키기 위해 추가 함수가 추가되었습니다. 예를 들어 Windows XP 이상에서 IPv6 및 IPv4를 모두 지원하는 새 이름 서비스 함수(예: getaddrinfogetnameinfo)가 추가되었습니다. 일부 이전 IPv4 전용 이름 서비스 함수(예: 함수의 getXbyY 클래스)는 더 이상 사용되지 않습니다.

Windows 소켓 함수에서 반환할 수 있는 오류 코드의 전체 목록은 Windows 소켓 오류 코드 섹션에 나와 있습니다.

Winsock 오류 처리

소켓 애플리케이션을 Winsock으로 포팅

Windows 소켓 오류 코드

Winsock 프로그래밍 고려 사항