다음을 통해 공유


오류 코드 - errno, h_errno 및 WSAGetLastError

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

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

BSD(Berkeley UNIX)와의 호환성을 위해 초기 버전의 Windows(예: Windows 95의 Windows 소켓 2 업데이트 및 Windows 98)에서는 BSD의 일반적인 Berkeley 오류 상수(일반적으로 errno.h에 있음)를 이에 상응하는 Windows Sockets 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)
    {...}

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

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

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

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

Winsock 오류 처리하기

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

Windows 소켓 오류 코드

Winsock 프로그래밍 고려 사항