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 equivalente do Windows Sockets para a função GetLastError do Windows. Os códigos de erro retornados pelos Soquetes do Windows são semelhantes às constantes de código de erro do soquete UNIX, mas todas as constantes são 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 pelos Soquetes do Windows não são disponibilizados por meio da variável errno. Além disso, para a classe de funções getXbyY, 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 de um thread em um processo multithreaded obter informações de erro específicas para cada thread.
Para compatibilidade com o Berkeley UNIX (BSD), as primeiras versões do Windows (como o Windows 95 com a Atualização do Windows Socket 2 e o Windows 98, por exemplo) redefiniram as constantes de erro regulares de Berkeley, normalmente encontradas em errno.h no BSD, como os erros equivalentes de 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 errno.h, usado com o Microsoft C/C++ e o Visual Studio.
O arquivo de cabeçalho Winsock2.h incluído no Microsoft Windows Software Development Kit (SDK), no Platform Software Development Kit (SDK) e no Visual Studio ainda contém um bloco de definições comentado em um bloco #ifdef 0 e #endif que definem os códigos de erro do soquete BSD como iguais às 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 remover a marca de comentário desse 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 do soquete BSD são definidos como valores muito diferentes dos usados em programas UNIX, BSD e Linux. Os desenvolvedores de aplicativos são muito incentivados a usar as constantes de erro do 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 escrito para usar o errno global, funcione corretamente em um ambiente de execução única. 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 a errno. (Em Soquetes do Windows, a função WSASetLastError pode ser usada para essa finalidade.)
Estilo típico do BSD
r = recv(...);
if (r == -1
&& errno == EWOULDBLOCK)
{...}
Estilo preferencial
r = recv(...);
if (r == -1 /* (but see below) */
&& WSAGetLastError() == EWOULDBLOCK)
{...}
Os estilos acima precisam da redefinição das constantes de erro do soquete BSD para constantes de erro do WSA para funcionar corretamente. Embora as constantes de erro consistentes com o Berkeley Sockets 4.3 sejam fornecidas para fins de compatibilidade, os aplicativos são altamente 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 de funções getXbyY, por exemplo) foram obsoletas.
Uma lista completa dos possíveis códigos de erro retornados pelas funções do Windows Sockets é fornecida na seção sobre Códigos de Erro do Windows Sockets.
Tópicos relacionados