Códigos de erro – errno, h_errno e WSAGetLastError

Em aplicativos Winsock, os códigos de erro são recuperados usando a função WSAGetLastError , o substituto do Windows Sockets para a função GetLastError do Windows. Os códigos de erro retornados pelo Windows Sockets são semelhantes às constantes de código de erro do soquete UNIX, mas as constantes são todas prefixadas com WSA. Portanto, em aplicativos Winsock, o código de erro WSAEWOULDBLOCK seria retornado, enquanto em aplicativos UNIX o código de erro EWOULDBLOCK seria retornado.

Os códigos de erro definidos pelo Windows Sockets não são disponibilizados por meio da variável errno . Além disso, para a classe getXbyY de funções, os códigos de erro não são disponibilizados por meio da variável h_errno . A função WSAGetLastError destina-se a fornecer uma maneira confiável para um thread em um processo multithread obter informações de erro por thread.

Para compatibilidade com o Berkeley UNIX (BSD), as versões iniciais do Windows (Windows 95 com a Atualização do Windows Socket 2 e o Windows 98, por exemplo) redefiniram constantes de erro regulares de Berkeley normalmente encontradas em errno.h no BSD como os erros equivalentes do WSA do Windows Sockets. Portanto, por exemplo, ECONNREFUSED foi definido como WSAECONNREFUSED no arquivo de cabeçalho Winsock.h . Nas versões subsequentes do Windows (Windows NT 3.1 e posterior) essas definições foram comentadas para evitar conflitos com o errno.h usado com o Microsoft C/C++ e o Visual Studio.

O arquivo de cabeçalho Winsock2.h incluído com o Microsoft Windows Software Development Kit (SDK), o SDK (Platform Software Development Kit) e o Visual Studio ainda contém um bloco de definições comentado em um bloco de #ifdef 0 e #endif que definem os códigos de erro do soquete BSD como os mesmos que as constantes de erro do WSA. Eles podem ser usados para fornecer alguma compatibilidade com programação de soquete UNIX, BSD e Linux. Para compatibilidade com o BSD, um aplicativo pode optar por alterar o Winsock2.h e descompactar esse bloco. No entanto, os desenvolvedores de aplicativos são fortemente desencorajados a cancelar o comentário desse bloco devido a conflitos inevitáveis com errno.h na maioria dos aplicativos. Além disso, os erros de soquete BSD são definidos como valores muito diferentes do que são usados em programas UNIX, BSD e Linux. Os desenvolvedores de aplicativos são muito incentivados a usar as constantes de erro WSA em aplicativos de soquete.

Essas definições permanecem comentadas no cabeçalho Winsock2.h em um bloco #ifdef 0 e #endif. Se um desenvolvedor de aplicativos insistir em usar os códigos de erro BSD para compatibilidade, um aplicativo poderá optar por incluir uma linha do formulário:

#include <windows.h>

#define errno WSAGetLastError()

Isso permite que o código de rede que foi gravado use o errno global funcione corretamente em um ambiente de thread único. Há algumas desvantagens muito sérias. Se um arquivo de origem incluir código que inspeciona errno para funções de soquete e não soquete, esse mecanismo não poderá ser usado. Além disso, não é possível que um aplicativo atribua um novo valor ao errno. (No Windows Sockets, a função WSASetLastError pode ser usada para essa finalidade.)

Estilo BSD típico

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

Estilo preferencial

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

Embora constantes de erro consistentes com o Berkeley Sockets 4.3 sejam fornecidas para fins de compatibilidade, os aplicativos são fortemente incentivados a usar as definições de código de erro do WSA. Isso ocorre porque os códigos de erro retornados por determinadas funções do Windows Sockets se enquadram no intervalo padrão de códigos de erro, conforme definido pelo Microsoft C©. Portanto, uma versão melhor do fragmento de código-fonte anterior é:

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

A especificação original do Winsock 1.1 definida em 1995 recomendou um conjunto de códigos de erro e listou os possíveis erros que podem ser retornados como resultado de cada função. O Windows Sockets 2 adicionou funções e recursos com outros códigos de erro do Windows Sockets retornados além daqueles listados na especificação original do Winsock. Funções adicionais foram adicionadas ao longo do tempo para aprimorar o Winsock para uso por desenvolvedores. Por exemplo, novas funções de serviço de nome (getaddrinfo e getnameinfo, por exemplo) foram adicionadas que dão suporte a IPv6 e IPv4 no Windows XP e posterior. Algumas das funções de serviço de nome somente IPv4 mais antigas (a classe getXbyY de funções, por exemplo) foram preteridas.

Uma lista completa de possíveis códigos de erro retornados pelas funções do Windows Sockets é fornecida na seção em Códigos de Erro do Windows Sockets.

Tratamento de erros de Winsock

Portabilidade de aplicativos de soquete para Winsock

Códigos de erro do Windows Sockets

Considerações sobre programação winsock