共用方式為


錯誤碼 - 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 中的一般 Berkeley 錯誤常數,使其成為對應的 Windows Sockets 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 Sockets 中,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 Sockets 函式所傳回的錯誤碼屬於 Microsoft C© 所定義之錯誤碼的標準範圍。 因此,上述原始程式碼片段的較佳版本為:

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

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

Windows Sockets 函式傳回之可能錯誤碼的完整列表,位於 Windows Sockets 錯誤碼一節中。

處理 Winsock 錯誤

將套接字應用程式移植到 Winsock

Windows 套接字錯誤碼

Winsock 程式設計考量