Коды ошибок : errno, h_errno и WSAGetLastError

В приложениях Winsock коды ошибок извлекаются с помощью функции WSAGetLastError , заменяющей сокеты Windows GetLastError . Коды ошибок, возвращаемые сокетами Windows, похожи на константы кода ошибок сокета UNIX, но все константы имеют префикс WSA. Таким образом, в приложениях Winsock будет возвращен код ошибки WSAEWOULDBLOCK, а в приложениях UNIX — код ошибки EWOULDBLOCK.

Коды ошибок, заданные сокетами Windows, недоступны через переменную errno . Кроме того, для класса функций getXbyY коды ошибок недоступны через переменную h_errno . Функция WSAGetLastError предназначена для обеспечения надежного способа получения потоком в многопотоковом процессе сведений об ошибках каждого потока.

Для обеспечения совместимости с Berkeley UNIX (BSD) ранние версии Windows (например, Windows 95 с windows Socket 2 Update и Windows 98) переопределяли обычные константы ошибок Беркли, которые обычно находятся в errno.h в BSD, как эквивалентные ошибки WSA сокетов Windows. Например, параметр ECONNREFUSED был определен как WSAECONNREFUSED в файле заголовка Winsock.h . В последующих версиях Windows (Windows NT 3.1 и более поздних версиях) эти определения были закомментированы, чтобы избежать конфликтов с errno.h, используемым с Microsoft C/C++ и Visual Studio.

Файл заголовка Winsock2.h , включенный в пакет средств разработки программного обеспечения Microsoft Windows (SDK), пакет средств разработки платформы (SDK) и Visual Studio, по-прежнему содержит блок закомментированных определений в #ifdef 0 и #endif блок, определяющий коды ошибок сокета BSD, которые будут совпадать с константами ошибок WSA. Их можно использовать для обеспечения совместимости с программированием сокетов UNIX, BSD и Linux. Для совместимости с BSD приложение может изменить Winsock2.h и раскомментировать этот блок. Однако разработчикам приложений настоятельно не рекомендуется раскомментивать этот блок из-за неизбежных конфликтов с errno.h в большинстве приложений. Кроме того, ошибки сокета BSD определяются очень разными значениями, которые используются в программах UNIX, BSD и Linux. Разработчикам приложений настоятельно рекомендуется использовать константы ошибок WSA в приложениях сокетов.

Эти определения остаются закомментированы в заголовке Winsock2.h в блоке #ifdef 0 и #endif. Если разработчик приложения настаивает на использовании кодов ошибок 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)
    {...}

Исходная спецификация Winsock 1.1, определенная в 1995 году, рекомендовала набор кодов ошибок и перечислила возможные ошибки, которые могут быть возвращены в результате выполнения каждой функции. Сокеты Windows 2 добавили функции и функции с другими кодами ошибок Сокетов Windows, возвращенными в дополнение к кодам, перечисленным в исходной спецификации Winsock. Со временем были добавлены дополнительные функции для улучшения Winsock для использования разработчиками. Например, добавлены новые функции службы имен (например, getaddrinfo и getnameinfo), поддерживающие как IPv6, так и IPv4 в Windows XP и более поздних версиях. Некоторые из старых функций службы имен только для IPv4 (например, класс функций getXbyY ) устарели.

Полный список возможных кодов ошибок, возвращаемых функциями Сокетов Windows, приведен в разделе Коды ошибок сокетов Windows.

Обработка ошибок Winsock

Перенос приложений сокетов в Winsock

Коды ошибок сокетов Windows

Рекомендации по программированию Winsock