錯誤碼 - errno、h_errno 和 WSAGetLastError

在 Winsock 應用程式中,會使用WSAGetLastError函式來擷取錯誤碼,Windows Sockets 取代Windows GetLastError 函式。 Windows Socket 傳回的錯誤碼與 UNIX 通訊端錯誤碼常數類似,但常數全都會加上 WSA。 因此在 Winsock 應用程式中,會傳回 WSAEWOULDBLOCK 錯誤碼,而在 UNIX 應用程式中,則會傳回 EWOULDBLOCK 錯誤碼。

Windows通訊端所設定的錯誤碼無法透過errno變數提供使用。 此外,對於函式的 getXbyY 類別,錯誤碼不會透過 h_errno 變數提供使用。 WSAGetLastError函式旨在為多執行緒進程中的執行緒提供可靠的方式,以取得每個執行緒的錯誤資訊。

為了與 Berkeley UNIX (BSD) 相容,Windows (Windows 95 的舊版與 Windows Socket 2 Update 和 Windows 98 相容,例如,) 在 BSD 上的errno.h 中,通常會在 errno.h中找到為對等的 Windows Sockets WSA 錯誤。 因此,例如,在Winsock.h標頭檔中,ECNNREFUSED 定義為 WSAECONNREFUSED。 在後續版本的 Windows (Windows NT 3.1 和更新版本中) ,這些定義已加上批註,以避免與 Microsoft C/C++ 和 Visual Studio 搭配使用的errno.h發生衝突。

Microsoft Windows 軟體發展工具組 (SDK) 、Platform Software Development Kit (SDK) 隨附的Winsock2.h標頭檔,而且Visual Studio仍然包含已批註化區塊,其中定義 BSD 通訊端錯誤碼與 WSA 錯誤常數相同的#ifdef 0 和 #endif 區塊。 這些可用來提供與 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 Sockets 中,WSASetLastError函式可用於此用途。)

一般 BSD 樣式

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

慣用樣式

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

雖然為相容性目的提供與 一致的錯誤常數 4.3,但強烈建議應用程式使用 WSA 錯誤碼定義。 這是因為某些 Windows Sockets 函式所傳回的錯誤碼屬於 Microsoft C© 所定義之錯誤碼的標準範圍。 因此,上述原始程式碼片段的較佳版本為:

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

1995 中定義的原始 Winsock 1.1 規格建議一組錯誤碼,並列出每個函式所傳回的可能錯誤。 Windows Sockets 2 除了原始 Winsock 規格中所列的錯誤碼之外,還新增了其他Windows通訊端錯誤碼的函式和功能。 已隨著時間新增其他函式,以增強 Winsock 以供開發人員使用。 例如,新的名稱服務函式 (getaddrinfogetnameinfo,例如) 新增,支援 Windows XP 和更新版本上的 IPv6 和 IPv4。 某些較舊的僅限 IPv4 名稱服務函式 (函式的 getXbyY 類別,例如) 已被取代。

Windows Sockets 函式所傳回之可能錯誤碼的完整清單,請參閱Windows通訊端錯誤碼一節。

處理 Winsock 錯誤

將通訊端應用程式移植到 Winsock

Windows通訊端錯誤碼

Winsock 程式設計考慮