Поделиться через


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

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

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

Ранние версии Windows (например, Windows 95 с обновлением Windows Socket 2 и Windows 98) для совместимости с Berkeley UNIX (BSD) переопределяли регулярные константы ошибок Berkeley, обычно содержащиеся в 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 Software Development Kit (SDK), Platform Software Development Kit (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)
    {...}

Для правильной работы приведенные выше стили требуют повторного определения констант сокетов BSD в константы ошибок WSA. Хотя константы ошибок, согласованные с Berkeley Sockets 4.3, предоставляются для обеспечения совместимости, приложения настоятельно рекомендуется использовать определения кода ошибки WSA. Это связано с тем, что коды ошибок, возвращаемые определенными функциями сокетов Windows, попадают в стандартный диапазон кодов ошибок, определенных Microsoft C©. Таким образом, лучшей версией предыдущего фрагмента исходного кода является следующее:

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

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

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

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

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

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

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