Udostępnij za pośrednictwem


Kody błędów — errno, h_errno i WSAGetLastError

W aplikacjach Winsock kody błędów są pobierane przy użyciu funkcji WSAGetLastError, która pełni rolę zamiennika dla funkcji gniazd systemu Windows GetLastError. Kody błędów zwracane przez sokety Windows są podobne do stałych kodów błędów gniazd w systemie UNIX, ale wszystkie stałe są poprzedzone prefiksem WSA. Dlatego w aplikacjach Winsock zostanie zwrócony kod błędu WSAEWOULDBLOCK, podczas gdy w aplikacjach SYSTEMU UNIX zostanie zwrócony kod błędu EWOULDBLOCK.

Kody błędów ustawione przez gniazda systemu Windows nie są udostępniane za pośrednictwem zmiennej errno. Ponadto w przypadku getXbyY klasy funkcji kody błędów nie są udostępniane za pośrednictwem zmiennej h_errno. Funkcja WSAGetLastError jest przeznaczona, aby zapewnić niezawodny sposób dla wątku w wielowątkowym procesie na uzyskiwanie informacji o błędach dla poszczególnych wątków.

Ze względu na zgodność z Berkeley UNIX (BSD), wczesne wersje systemu Windows (na przykład Windows 95 z Windows Socket 2 Update i Windows 98) ponownie zdefiniowały standardowe stałe błędów Berkeley, zwykle znajdujące się w errno.h na BSD, jako odpowiedniki błędów Windows Sockets WSA. Na przykład ECONNREFUSED został zdefiniowany jako WSAECONNREFUSED w pliku nagłówka Winsock.h. W kolejnych wersjach systemu Windows (Windows NT 3.1 i nowszych) te definicje zostały oznaczone jako komentarz, aby uniknąć konfliktów z errno.h używanych z językami Microsoft C/C++ i Visual Studio.

Plik nagłówka Winsock2.h dołączony do zestawu Microsoft Windows Software Development Kit (SDK), Zestaw SDK Platformy i Visual Studio nadal zawiera wykomentowany blok definicji w bloku #ifdef 0 i #endif, który definiuje kody błędów gniazda BSD jako takie same jak stałe błędów WSA. Mogą one służyć do zapewnienia zgodności z programowaniem gniazd w systemach UNIX, BSD i Linux. Aby zapewnić zgodność z BSD, aplikacja może wybrać zmianę Winsock2.h i usunąć komentarz z tego bloku. Jednak deweloperom aplikacji stanowczo odradza się usunięcie komentarza w tym bloku z powodu nieuniknionych konfliktów z errno.h w większości aplikacji. Ponadto błędy gniazda BSD są definiowane do bardzo różnych wartości niż są używane w programach z systemami UNIX, BSD i Linux. Deweloperzy aplikacji są bardzo zdecydowanie zachęcani do używania stałych błędów WSA w aplikacjach gniazdowych.

Te definicje pozostają komentowane w nagłówku Winsock2.h w bloku #ifdef 0 i #endif. Jeśli deweloper aplikacji nalega na używanie kodów błędów BSD pod kątem zgodności, aplikacja może wybrać dołączenie wiersza formularza:

#include <windows.h>

#define errno WSAGetLastError()

Dzięki temu kod sieciowy, który został napisany do używania globalnej errno, może działać poprawnie w środowisku jednowątkowym. Istnieją bardzo poważne wady. Jeśli plik źródłowy zawiera kod, który sprawdza errno zarówno dla funkcji gniazdowych, jak i nienależących do gniazd, tego mechanizmu nie można użyć. Ponadto aplikacja nie może przypisać nowej wartości do errno. (W przypadku gniazd systemu Windows funkcja WSASetLastError może być używana w tym celu).

Typowy styl BSD

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

Preferowany styl

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

Powyższe style wymagają ponownej definicji stałych błędów gniazda BSD do stałych błędów WSA w celu poprawnego działania. Mimo że stałe błędów zgodne z Berkeley Sockets 4.3 są zapewniane dla celów zgodności, aplikacje są zdecydowanie zachęcane do używania definicji kodów błędów WSA. Dzieje się tak, ponieważ kody błędów zwracane przez niektóre funkcje Windows Sockets należą do standardowego zakresu kodów błędów zdefiniowanych przez firmę Microsoft C©. W związku z tym lepszą wersją poprzedniego fragmentu kodu źródłowego jest:

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

Oryginalna specyfikacja winsock 1.1 zdefiniowana w 1995 r. zaleciła zestaw kodów błędów i wymieniła możliwe błędy, które mogą być zwracane w wyniku każdej funkcji. Windows Sockets 2 dodał funkcje i cechy, zwracając kody błędów gniazd Windows inne niż te wymienione w oryginalnej specyfikacji Winsock. Dodatkowe funkcje zostały dodane z upływem czasu, aby ulepszyć środowisko Winsock do użytku przez deweloperów. Na przykład dodano nowe funkcje usługi nazw (getaddrinfo i getnameinfo, na przykład), które obsługują protokoły IPv6 i IPv4 w systemie Windows XP i nowszych wersjach. Niektóre ze starszych funkcji usługi nazw tylko dla IPv4 (na przykład funkcje klasy getXbyY) zostały oznaczone do wycofania.

Pełna lista możliwych kodów błędów zwracanych przez funkcje gniazd systemu Windows znajduje się w sekcji na temat kodów błędów gniazd systemu Windows.

Obsługa błędów Winsock

Przenoszenie aplikacji socketów do Winsock

kody błędów gniazd systemu Windows

Zagadnienia dotyczące programowania Winsock