错误代码 - errno、h_errno 和 WSAGetLastError
在 Winsock 应用程序中,系统使用 WSAGetLastError 函数检索错误代码,Windows 套接字会取代 Windows GetLastError 函数。 Windows 套接字返回的错误代码类似于 UNIX 套接字错误代码常量,但常量都以 WSA 为前缀。 因此,在 Winsock 应用程序中,将返回 WSAEWOULDBLOCK 错误代码,而在 UNIX 应用程序中,将返回 EWOULDBLOCK 错误代码。
Windows 套接字设置的错误代码不能通过 errno 变量来提供。 此外,对于 getXbyY 类函数,错误代码不会通过 h_errno 变量提供。 WSAGetLastError 函数旨在为多线程进程中的线程提供可靠的方法来获取每线程错误信息。
为了与 Berkeley UNIX (BSD) 兼容,早期版本的 Windows(例如,带有 Windows 套接字 2 更新的 Windows 95 和 Windows 98)将通常在 BSD 上的 errno.h 中找到的 Berkeley 错误常量重新定义为同等 Windows套接字 WSA 错误。 例如,ECONNREFUSED 在 Winsock.h 头文件中定义为 WSAECONNREFUSED。 在后续版本的 Windows(Windows NT 3.1 及更高版本中),这些定义被注释掉,以避免与用于 Microsoft C/C++ 和 Visual Studio 的 errno.h 冲突。
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 错误常量。
这些定义在 #ifdef 0 和 #endif 块内的 Winsock2.h 标头中仍被注释掉了。 如果应用程序开发人员坚持使用 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)
{...}
1995 年定义的原始 Winsock 1.1 规范建议使用一组错误代码,并列出了可能因每个函数返回的错误。 Windows Sockets 2 添加了函数和功能,除了原始 Winsock 规范中列出的错误代码外,它还返回了其他 Windows Sockets 错误代码。 随着时间推移添加了其他函数,以增强 Winsock 供开发人员使用。 例如,添加了新的名称服务函数(getaddrinfo 和 getnameinfo),支持 Windows XP 及更高版本上的 IPv6 和 IPv4。 某些较旧的仅限 IPv4 的名称服务函数(例如,getXbyY 类函数)已弃用。
Windows 套接字错误代码部分中提供了 Windows 套接字函数返回的可能错误代码的完整列表。
相关主题