错误代码 - 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 95 与 Windows 套接字 2 更新和 Windows 98 兼容,例如,) 重新定义了 BSD 上的 errno.h 中通常发现的常规 Berkeley 错误常量作为等效的 Windows 套接字 WSA 错误。 例如,在 Winsock.h 头文件中,ECONNREFUSED 定义为 WSAECONNREFUSED。 在 Windows (Windows NT 3.1 及更高版本的后续版本中,) 注释掉了这些定义,以避免与 Microsoft C/C++ 和 Visual Studio 中使用的 errno.h 冲突。

Microsoft Windows 软件开发工具包附带 的 Winsock2.h 头文件 (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)
    {...}

1995 年定义的原始 Winsock 1.1 规范推荐了一组错误代码,并列出了每个函数可能返回的错误。 除了原始 Winsock 规范中列出的函数和功能外,Windows 套接字 2 还添加了其他 Windows 套接字错误代码。 随着时间的推移,添加了其他函数,以增强 Winsock 供开发人员使用。 例如, (getaddrinfogetnameinfo 的新名称服务函数,例如,在 Windows XP 及更高版本上添加了同时支持 IPv6 和 IPv4 的) 。 某些较旧的仅限 IPv4 的名称服务函数 (getXbyY 类函数,例如) 已弃用。

Windows 套接字错误代码部分提供了 Windows 套接字函数可能返回 的错误代码的完整列表。

处理 Winsock 错误

将套接字应用程序移植到 Winsock

Windows 套接字错误代码

Winsock 编程注意事项