最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C語(yǔ)言WSAGetLastError函數(shù)全面介紹

 更新時(shí)間:2026年02月14日 09:26:22   作者:學(xué)編程的鬧鐘  
WSAGetLastError()是WindowsSocketsAPI中用于獲取網(wǎng)絡(luò)操作錯(cuò)誤代碼的重要函數(shù),它返回線程最后一次網(wǎng)絡(luò)操作的錯(cuò)誤代碼,代替了傳統(tǒng)的全局錯(cuò)誤變量,通過(guò)本文的全面介紹,我們將深入探討WSAGetLastError()函數(shù)的各個(gè)方面,感興趣的朋友跟隨小編一起看看吧

一、WSAGetLastError函數(shù)概述

WSAGetLastError()是Windows Sockets API中至關(guān)重要的錯(cuò)誤處理函數(shù),它返回線程最后一次網(wǎng)絡(luò)操作錯(cuò)誤代碼。該函數(shù)在多線程環(huán)境中替代傳統(tǒng)的全局錯(cuò)誤變量,通過(guò)調(diào)用線程級(jí)錯(cuò)誤狀態(tài)機(jī)制實(shí)現(xiàn)兼容性。

1.1 函數(shù)原型與基本用法

#include <winsock2.h>
int WSAGetLastError(void);

基本調(diào)用方法非常簡(jiǎn)單:

// 示例:檢查Socket操作錯(cuò)誤
SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (s == INVALID_SOCKET) {
    int errorCode = WSAGetLastError();
    printf("Socket創(chuàng)建失敗,錯(cuò)誤代碼: %d\n", errorCode);
}

1.2 與GetLastError的區(qū)別

雖然WSAGetLastError()GetLastError()功能相似,但前者專(zhuān)門(mén)針對(duì)Windows Sockets操作。在占先式Windows環(huán)境下,WSAGetLastError()實(shí)際上會(huì)調(diào)用GetLastError()來(lái)獲得所有在每線程基礎(chǔ)上的Win32 API函數(shù)的錯(cuò)誤狀態(tài)。

二、Windows Sockets錯(cuò)誤碼分類(lèi)體系

Windows Sockets錯(cuò)誤碼采用系統(tǒng)化分類(lèi)方法,在頭文件winsock.h中定義了所有錯(cuò)誤碼。這些錯(cuò)誤碼可分為四個(gè)主要部分:

2.1 標(biāo)準(zhǔn)C錯(cuò)誤碼的Windows Sockets版本

這類(lèi)錯(cuò)誤碼解決了不同C編譯器對(duì)標(biāo)準(zhǔn)C錯(cuò)誤碼不一致定義的問(wèn)題,主要包括:

  • 基礎(chǔ)操作錯(cuò)誤:如中斷調(diào)用、文件句柄錯(cuò)誤等
  • 權(quán)限與訪問(wèn)錯(cuò)誤:權(quán)限被拒絕、地址無(wú)效等
  • 參數(shù)與狀態(tài)錯(cuò)誤:無(wú)效參數(shù)、太多打開(kāi)文件等

這些錯(cuò)誤碼與標(biāo)準(zhǔn)C錯(cuò)誤碼對(duì)應(yīng),但添加了WSA前綴,例如WSAEINTR對(duì)應(yīng)EINTR。

2.2 Berkeley Sockets錯(cuò)誤碼的Windows版本

為確保原有軟件的可移植性,Windows Sockets包含了Berkeley Sockets定義的全部錯(cuò)誤碼:

  • 網(wǎng)絡(luò)操作錯(cuò)誤:網(wǎng)絡(luò)不可達(dá)、連接被重置等
  • 協(xié)議與地址錯(cuò)誤:協(xié)議錯(cuò)誤、地址族不支持等
  • 連接與通信錯(cuò)誤:連接中止、連接超時(shí)等

2.3 Windows Sockets特有錯(cuò)誤碼

這部分錯(cuò)誤碼是Windows Sockets的擴(kuò)展,包括:

  • 系統(tǒng)狀態(tài)錯(cuò)誤:網(wǎng)絡(luò)子系統(tǒng)不可用、Winsock未初始化等
  • 服務(wù)提供者錯(cuò)誤:無(wú)效服務(wù)提供者、提供者初始化失敗等
  • 擴(kuò)展操作錯(cuò)誤:重疊I/O操作、異步操作狀態(tài)等

2.4 域名服務(wù)相關(guān)錯(cuò)誤碼

這類(lèi)錯(cuò)誤由getXbyY()WSAAsyncGetXByY()函數(shù)返回,相當(dāng)于Berkeley軟件中由變量h_errno返回的錯(cuò)誤:

  • 名稱(chēng)解析錯(cuò)誤:主機(jī)未找到、重試操作等
  • 服務(wù)恢復(fù)錯(cuò)誤:不可恢復(fù)的錯(cuò)誤、無(wú)數(shù)據(jù)可用等

三、錯(cuò)誤碼范圍詳解

3.1 系統(tǒng)級(jí)錯(cuò)誤碼范圍 (0-999)

這些錯(cuò)誤碼通常與操作系統(tǒng)基礎(chǔ)功能相關(guān):

0-99范圍:基礎(chǔ)系統(tǒng)錯(cuò)誤

  • 基本操作狀態(tài)和簡(jiǎn)單錯(cuò)誤代碼
  • 包括成功操作(0)和基礎(chǔ)功能錯(cuò)誤

100-199范圍:擴(kuò)展系統(tǒng)錯(cuò)誤

  • 較為復(fù)雜的系統(tǒng)級(jí)錯(cuò)誤
  • 涉及資源分配、權(quán)限驗(yàn)證等

3.2 核心Socket錯(cuò)誤碼范圍 (10000-11000)

這是最常見(jiàn)的Socket錯(cuò)誤碼范圍,涵蓋了大多數(shù)網(wǎng)絡(luò)編程錯(cuò)誤:

10000-10099范圍:基礎(chǔ)Socket操作錯(cuò)誤

  • 包括參數(shù)錯(cuò)誤、狀態(tài)錯(cuò)誤和資源限制
  • 常見(jiàn)錯(cuò)誤如WSAEINTR(10004)、WSAEBADF(10009)等

10030-10049范圍:地址與協(xié)議錯(cuò)誤

  • 地址族不支持、協(xié)議錯(cuò)誤等
  • WSAEAFNOSUPPORT(10047)、WSAEPROTONOSUPPORT(10043)等

10050-10069范圍:網(wǎng)絡(luò)連接錯(cuò)誤

  • 網(wǎng)絡(luò)狀態(tài)、連接問(wèn)題和主機(jī)通信錯(cuò)誤
  • 包括WSAENETDOWN(10050)、WSAECONNREFUSED(10061)等

3.3 高級(jí)網(wǎng)絡(luò)錯(cuò)誤碼范圍 (11000-12000)

這部分錯(cuò)誤碼涉及更復(fù)雜的網(wǎng)絡(luò)服務(wù)和名稱(chēng)解析:

11000-11099范圍:名稱(chēng)服務(wù)錯(cuò)誤

  • 主機(jī)查找、域名解析相關(guān)問(wèn)題
  • WSAHOST_NOT_FOUND(11001)、WSATRY_AGAIN(11002)等

3.4 特殊錯(cuò)誤碼范圍

操作系統(tǒng)相關(guān)錯(cuò)誤碼:這些錯(cuò)誤碼的值依賴(lài)于具體操作系統(tǒng):

  • WSA_INVALID_HANDLE、WSA_NOT_ENOUGH_MEMORY
  • 通常映射到底層操作系統(tǒng)錯(cuò)誤代碼

四、動(dòng)態(tài)獲取錯(cuò)誤碼信息的方法

4.1 使用FormatMessage獲取錯(cuò)誤描述

#include <winsock2.h>
#include <windows.h>
#include <stdio.h>
void PrintWSAError(int errorCode) {
    if (errorCode == 0) {
        printf("操作成功完成,無(wú)錯(cuò)誤發(fā)生。\n");
        return;
    }
    LPSTR errorMsg = NULL;
    DWORD flags = FORMAT_MESSAGE_ALLOCATE_BUFFER | 
                  FORMAT_MESSAGE_FROM_SYSTEM | 
                  FORMAT_MESSAGE_IGNORE_INSERTS;
    DWORD msgLength = FormatMessageA(
        flags,
        NULL,
        errorCode,
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
        (LPSTR)&errorMsg,
        0,
        NULL
    );
    if (msgLength > 0) {
        printf("錯(cuò)誤代碼: %d (0x%08X)\n", errorCode, errorCode);
        printf("錯(cuò)誤描述: %s", errorMsg);
        LocalFree(errorMsg);
    } else {
        printf("無(wú)法獲取錯(cuò)誤代碼 %d 的描述。\n", errorCode);
    }
}
// 使用示例
void ExampleUsage() {
    SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (s == INVALID_SOCKET) {
        int errorCode = WSAGetLastError();
        PrintWSAError(errorCode);
    }
}

4.2 增強(qiáng)版錯(cuò)誤信息獲取函數(shù)

#include <winsock2.h>
#include <windows.h>
#include <stdio.h>
typedef struct {
    int errorCode;
    const char* errorName;
    const char* description;
} WSAErrorInfo;
// 獲取完整的錯(cuò)誤信息,包括可能的模塊信息
void GetCompleteWSAErrorInfo(int errorCode) {
    printf("=== Windows Sockets錯(cuò)誤分析報(bào)告 ===\n");
    printf("錯(cuò)誤代碼: %d (0x%08X)\n", errorCode, errorCode);
    // 獲取系統(tǒng)錯(cuò)誤描述
    LPSTR sysErrorMsg = NULL;
    DWORD sysMsgLength = FormatMessageA(
        FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
        NULL, errorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
        (LPSTR)&sysErrorMsg, 0, NULL);
    if (sysMsgLength > 0) {
        printf("系統(tǒng)描述: %s", sysErrorMsg);
        LocalFree(sysErrorMsg);
    }
    // 錯(cuò)誤分類(lèi)信息
    printf("錯(cuò)誤分類(lèi): ");
    if (errorCode >= 10000 && errorCode < 11000) {
        printf("核心Socket錯(cuò)誤\n");
    } else if (errorCode >= 11000 && errorCode < 12000) {
        printf("名稱(chēng)服務(wù)錯(cuò)誤\n");
    } else if (errorCode < 1000) {
        printf("系統(tǒng)基礎(chǔ)錯(cuò)誤\n");
    } else {
        printf("特殊或擴(kuò)展錯(cuò)誤\n");
    }
    // 建議的解決措施
    PrintSuggestedSolution(errorCode);
}
// 根據(jù)錯(cuò)誤代碼提供解決建議
void PrintSuggestedSolution(int errorCode) {
    printf("建議處理措施: ");
    switch (errorCode) {
        case WSANOTINITIALISED:
            printf("請(qǐng)確保已成功調(diào)用WSAStartup()進(jìn)行初始化。\n");
            break;
        case WSAENETDOWN:
            printf("檢查網(wǎng)絡(luò)連接是否正常,網(wǎng)絡(luò)子系統(tǒng)可能已失效。\n");
            break;
        case WSAEADDRINUSE:
            printf("地址已被使用,請(qǐng)更換端口或設(shè)置SO_REUSEADDR選項(xiàng)。\n");
            break;
        case WSAECONNREFUSED:
            printf("連接被拒絕,確保目標(biāo)主機(jī)和端口有服務(wù)在監(jiān)聽(tīng)。\n");
            break;
        case WSAETIMEDOUT:
            printf("連接超時(shí),檢查網(wǎng)絡(luò)狀況或調(diào)整超時(shí)設(shè)置。\n");
            break;
        default:
            printf("請(qǐng)參考Microsoft官方文檔獲取特定錯(cuò)誤代碼的解決方案。\n");
            break;
    }
}

4.3 批量獲取系統(tǒng)所有錯(cuò)誤碼信息

#include <winsock2.h>
#include <windows.h>
#include <stdio.h>
void DumpAllWSAErrorCodes(int startRange, int endRange, const char* filename) {
    FILE* logFile = fopen(filename, "w");
    if (!logFile) {
        printf("無(wú)法創(chuàng)建日志文件: %s\n", filename);
        return;
    }
    fprintf(logFile, "Windows Sockets錯(cuò)誤碼范圍: %d - %d\n\n", startRange, endRange);
    for (int code = startRange; code <= endRange; code++) {
        LPSTR errorMsg = NULL;
        DWORD flags = FORMAT_MESSAGE_ALLOCATE_BUFFER | 
                      FORMAT_MESSAGE_FROM_SYSTEM | 
                      FORMAT_MESSAGE_IGNORE_INSERTS;
        DWORD msgLength = FormatMessageA(
            flags,
            NULL,
            code,
            MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
            (LPSTR)&errorMsg,
            0,
            NULL
        );
        if (msgLength > 0) {
            fprintf(logFile, "0x%08X (%d): %s", code, code, errorMsg);
            LocalFree(errorMsg);
        }
        // 每100個(gè)錯(cuò)誤碼輸出進(jìn)度
        if (code % 100 == 0) {
            printf("已處理錯(cuò)誤碼至: %d\n", code);
        }
    }
    fclose(logFile);
    printf("錯(cuò)誤碼已導(dǎo)出至: %s\n", filename);
}
// 專(zhuān)門(mén)導(dǎo)出WSA錯(cuò)誤碼的函數(shù)
void ExportWSAErrorCodes() {
    // 導(dǎo)出核心Socket錯(cuò)誤碼
    DumpAllWSAErrorCodes(10000, 11000, "wsa_core_errors.txt");
    // 導(dǎo)出名稱(chēng)服務(wù)錯(cuò)誤碼
    DumpAllWSAErrorCodes(11000, 11100, "wsa_name_service_errors.txt");
}

4.4 錯(cuò)誤碼查詢(xún)工具的使用

除了編程方式,Windows還提供了命令行工具來(lái)查看錯(cuò)誤碼:

4.4.1 使用net.exe命令查詢(xún)Socket錯(cuò)誤

@echo off
REM 查詢(xún)特定WSA錯(cuò)誤碼
net helpmsg 10048
REM 輸出: Address already in use.
REM 批量查詢(xún)WSA錯(cuò)誤碼
for /l %%i in (10048,1,10065) do @echo Error %%i: & net helpmsg %%i

4.4.2 使用PowerShell查詢(xún)WSA錯(cuò)誤碼

# PowerShell WSA錯(cuò)誤碼查詢(xún)函數(shù)
function Get-WSAErrorDescription {
    param([int]$ErrorCode)
    # 嘗試從系統(tǒng)獲取錯(cuò)誤描述
    $ErrorText = New-Object -TypeName System.ComponentModel.Win32Exception -ArgumentList $ErrorCode
    $HexCode = "0x" + $ErrorCode.ToString("X8")
    # 錯(cuò)誤分類(lèi)
    if ($ErrorCode -ge 10000 -and $ErrorCode -lt 11000) {
        $Category = "Core Socket Error"
    } elseif ($ErrorCode -ge 11000 -and $ErrorCode -lt 12000) {
        $Category = "Name Service Error"
    } else {
        $Category = "System Error"
    }
    return @{
        Code = $ErrorCode
        HexCode = $HexCode
        Description = $ErrorText.Message
        Category = $Category
    }
}
# 使用示例
$errorInfo = Get-WSAErrorDescription -ErrorCode 10048
Write-Host "錯(cuò)誤代碼: $($errorInfo.Code) ($($errorInfo.HexCode))"
Write-Host "描述: $($errorInfo.Description)"
Write-Host "分類(lèi): $($errorInfo.Category)"

4.4.3 自定義錯(cuò)誤碼查詢(xún)工具

#include <winsock2.h>
#include <windows.h>
#include <stdio.h>
#include <map>
class WSAErrorLookup {
private:
    std::map<int, const char*> errorMap;
public:
    WSAErrorLookup() {
        InitializeErrorMap();
    }
    void InitializeErrorMap() {
        // 核心Socket錯(cuò)誤碼映射
        errorMap[WSAEINTR] = "Interrupted function call";
        errorMap[WSAEBADF] = "Bad file number";
        errorMap[WSAEACCES] = "Permission denied";
        errorMap[WSAEFAULT] = "Bad address";
        errorMap[WSAEINVAL] = "Invalid argument";
        errorMap[WSAEMFILE] = "Too many open files";
        errorMap[WSAEWOULDBLOCK] = "Resource temporarily unavailable";
        errorMap[WSAEINPROGRESS] = "Operation now in progress";
        errorMap[WSAEALREADY] = "Operation already in progress";
        errorMap[WSAENOTSOCK] = "Socket operation on non-socket";
        errorMap[WSAEDESTADDRREQ] = "Destination address required";
        errorMap[WSAEMSGSIZE] = "Message too long";
        errorMap[WSAEPROTOTYPE] = "Protocol wrong type for socket";
        errorMap[WSAENOPROTOOPT] = "Protocol not available";
        errorMap[WSAEPROTONOSUPPORT] = "Protocol not supported";
        errorMap[WSAESOCKTNOSUPPORT] = "Socket type not supported";
        errorMap[WSAEOPNOTSUPP] = "Operation not supported";
        errorMap[WSAEPFNOSUPPORT] = "Protocol family not supported";
        errorMap[WSAEAFNOSUPPORT] = "Address family not supported by protocol family";
        errorMap[WSAEADDRINUSE] = "Address already in use";
        errorMap[WSAEADDRNOTAVAIL] = "Cannot assign requested address";
        errorMap[WSAENETDOWN] = "Network is down";
        errorMap[WSAENETUNREACH] = "Network is unreachable";
        errorMap[WSAENETRESET] = "Network dropped connection on reset";
        errorMap[WSAECONNABORTED] = "Software caused connection abort";
        errorMap[WSAECONNRESET] = "Connection reset by peer";
        errorMap[WSAENOBUFS] = "No buffer space available";
        errorMap[WSAEISCONN] = "Socket is already connected";
        errorMap[WSAENOTCONN] = "Socket is not connected";
        errorMap[WSAESHUTDOWN] = "Cannot send after socket shutdown";
        errorMap[WSAETIMEDOUT] = "Connection timed out";
        errorMap[WSAECONNREFUSED] = "Connection refused";
        errorMap[WSAEHOSTDOWN] = "Host is down";
        errorMap[WSAEHOSTUNREACH] = "No route to host";
        errorMap[WSASYSNOTREADY] = "Network subsystem is unavailable";
        errorMap[WSAVERNOTSUPPORTED] = "Winsock.dll version out of range";
        errorMap[WSANOTINITIALISED] = "Successful WSAStartup not yet performed";
        errorMap[WSAEDISCON] = "Graceful shutdown in progress";
        // ... 可以繼續(xù)添加更多錯(cuò)誤碼映射
    }
    void LookupError(int errorCode) {
        auto it = errorMap.find(errorCode);
        if (it != errorMap.end()) {
            printf("錯(cuò)誤代碼: %d\n", errorCode);
            printf("錯(cuò)誤描述: %s\n", it->second);
        } else {
            printf("未知錯(cuò)誤代碼: %d\n", errorCode);
            // 嘗試從系統(tǒng)獲取描述
            LPSTR sysMsg = NULL;
            DWORD msgLen = FormatMessageA(
                FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
                NULL, errorCode, 0, (LPSTR)&sysMsg, 0, NULL);
            if (msgLen > 0) {
                printf("系統(tǒng)提供的描述: %s", sysMsg);
                LocalFree(sysMsg);
            }
        }
    }
};

五、錯(cuò)誤處理最佳實(shí)踐

5.1 立即保存錯(cuò)誤碼模式

由于WSAGetLastError()返回的是線程的最后錯(cuò)誤代碼,在調(diào)用其他API前必須立即保存:

#include <winsock2.h>
#include <stdio.h>
// 正確的錯(cuò)誤處理方式
void SafeSocketOperation() {
    SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (s == INVALID_SOCKET) {
        int err = WSAGetLastError();  // 立即保存錯(cuò)誤碼
        // 使用保存的錯(cuò)誤碼進(jìn)行后續(xù)處理
        printf("Socket創(chuàng)建失敗,錯(cuò)誤代碼: %d\n", err);
        HandleSocketError(err);
        return;
    }
    // 其他Socket操作...
    int result = connect(s, ...);
    if (result == SOCKET_ERROR) {
        int err = WSAGetLastError();  // 立即保存錯(cuò)誤碼
        printf("連接失敗,錯(cuò)誤代碼: %d\n", err);
        HandleSocketError(err);
        closesocket(s);
        return;
    }
}

5.2 錯(cuò)誤處理封裝宏

創(chuàng)建一套完整的錯(cuò)誤處理宏可以顯著提高代碼質(zhì)量:

#include <winsock2.h>
#include <stdio.h>
// 基礎(chǔ)錯(cuò)誤檢查宏
#define CHECK_SOCKET_RESULT(socket_call) \
    do { \
        int __result = (socket_call); \
        if (__result == SOCKET_ERROR) { \
            int __err = WSAGetLastError(); \
            LogSocketError(__FILE__, __LINE__, __err, #socket_call); \
            return SOCKET_ERROR; \
        } \
    } while(0)
// 帶錯(cuò)誤處理的Socket API調(diào)用宏
#define SOCKET_CALL_WITH_HANDLE(socket_call, error_handler) \
    do { \
        int __result = (socket_call); \
        if (__result == SOCKET_ERROR) { \
            int __err = WSAGetLastError(); \
            error_handler(__err, #socket_call); \
        } \
    } while(0)
// Socket錯(cuò)誤日志記錄函數(shù)
void LogSocketError(const char* file, int line, int errorCode, const char* apiName) {
    LPSTR errorMsg = NULL;
    FormatMessageA(
        FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
        NULL, errorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
        (LPSTR)&errorMsg, 0, NULL);
    printf("[SOCKET ERROR] %s:%d - %s 失敗 (代碼: %d)\n", 
           file, line, apiName, errorCode);
    printf("        %s\n", errorMsg ? errorMsg : "無(wú)法獲取錯(cuò)誤描述");
    if (errorMsg) LocalFree(errorMsg);
}

5.3 高級(jí)錯(cuò)誤處理框架

對(duì)于大型網(wǎng)絡(luò)應(yīng)用程序,建議實(shí)現(xiàn)完整的錯(cuò)誤處理框架:

#include <winsock2.h>
#include <windows.h>
#include <stdio.h>
#include <time.h>
typedef enum {
    SOCKET_SEVERITY_INFO,
    SOCKET_SEVERITY_WARNING,
    SOCKET_SEVERITY_ERROR,
    SOCKET_SEVERITY_CRITICAL
} SOCKET_ERROR_SEVERITY;
typedef struct {
    int errorCode;
    SOCKET_ERROR_SEVERITY severity;
    char functionName[128];
    char sourceFile[256];
    int lineNumber;
    time_t timestamp;
    DWORD threadId;
    char description[512];
} SOCKET_ERROR_INFO;
class SocketErrorHandler {
private:
    static CRITICAL_SECTION cs;
    static HANDLE hLogFile;
    static bool initialized;
public:
    static bool Initialize(const char* logFilePath) {
        if (initialized) return true;
        InitializeCriticalSection(&cs);
        hLogFile = CreateFileA(logFilePath, GENERIC_WRITE, FILE_SHARE_READ, 
                              NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
        if (hLogFile == INVALID_HANDLE_VALUE) return false;
        SetFilePointer(hLogFile, 0, NULL, FILE_END);
        initialized = true;
        return true;
    }
    static void LogError(SOCKET_ERROR_SEVERITY severity, const char* function, 
                        const char* file, int line, int errorCode, const char* format, ...) {
        if (!initialized) return;
        EnterCriticalSection(&cs);
        SOCKET_ERROR_INFO errorInfo = {0};
        errorInfo.errorCode = errorCode;
        errorInfo.severity = severity;
        strncpy(errorInfo.functionName, function, sizeof(errorInfo.functionName)-1);
        strncpy(errorInfo.sourceFile, file, sizeof(errorInfo.sourceFile)-1);
        errorInfo.lineNumber = line;
        errorInfo.threadId = GetCurrentThreadId();
        errorInfo.timestamp = time(NULL);
        // 格式化描述信息
        va_list args;
        va_start(args, format);
        vsnprintf(errorInfo.description, sizeof(errorInfo.description)-1, format, args);
        va_end(args);
        // 寫(xiě)入日志文件
        if (hLogFile != INVALID_HANDLE_VALUE) {
            DWORD bytesWritten;
            WriteFile(hLogFile, &errorInfo, sizeof(SOCKET_ERROR_INFO), &bytesWritten, NULL);
        }
        // 控制臺(tái)輸出
        OutputErrorToConsole(&errorInfo);
        LeaveCriticalSection(&cs);
    }
    static void Cleanup() {
        if (hLogFile != INVALID_HANDLE_VALUE) {
            CloseHandle(hLogFile);
        }
        DeleteCriticalSection(&cs);
        initialized = false;
    }
private:
    static void OutputErrorToConsole(const SOCKET_ERROR_INFO* errorInfo) {
        const char* severityText[] = {"信息", "警告", "錯(cuò)誤", "嚴(yán)重"};
        struct tm* timeinfo = localtime(&errorInfo->timestamp);
        printf("[%s] %04d-%02d-%02d %02d:%02d:%02d [線程: %lu]\n",
                severityText[errorInfo->severity],
                timeinfo->tm_year + 1900, timeinfo->tm_mon + 1, timeinfo->tm_mday,
                timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec,
                errorInfo->threadId);
        printf("  文件: %s, 行號(hào): %d, 函數(shù): %s\n", 
               errorInfo->sourceFile, errorInfo->lineNumber, errorInfo->functionName);
        printf("  錯(cuò)誤代碼: %d (0x%08X)\n", errorInfo->errorCode, errorInfo->errorCode);
        LPSTR systemDescription = NULL;
        if (FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
                         NULL, errorInfo->errorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
                         (LPSTR)&systemDescription, 0, NULL)) {
            printf("  系統(tǒng)描述: %s", systemDescription);
            LocalFree(systemDescription);
        }
        printf("  描述: %s\n\n", errorInfo->description);
    }
};
// 靜態(tài)成員初始化
CRITICAL_SECTION SocketErrorHandler::cs;
HANDLE SocketErrorHandler::hLogFile = INVALID_HANDLE_VALUE;
bool SocketErrorHandler::initialized = false;
// 使用示例
void ExampleNetworkFunction() {
    SocketErrorHandler::Initialize("socket_errors.log");
    SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (s == INVALID_SOCKET) {
        int err = WSAGetLastError();
        SocketErrorHandler::LogError(SOCKET_SEVERITY_ERROR, "socket", 
                                    __FILE__, __LINE__, err, 
                                    "無(wú)法創(chuàng)建TCP socket");
    }
    SocketErrorHandler::Cleanup();
}

六、調(diào)試技巧與高級(jí)主題

6.1 Visual Studio調(diào)試技巧

在Visual Studio調(diào)試時(shí),可以使用特殊技術(shù)查看Socket錯(cuò)誤信息:

  • 查看最近Socket錯(cuò)誤:在Watch窗口添加@err,hr
  • 條件斷點(diǎn):設(shè)置條件斷點(diǎn)只在Socket錯(cuò)誤發(fā)生時(shí)觸發(fā)
  • 內(nèi)存窗口監(jiān)控:監(jiān)控特定的Socket狀態(tài)變量

6.2 錯(cuò)誤碼與異常處理集成

將Socket錯(cuò)誤碼與C++異常處理機(jī)制結(jié)合:

#include <winsock2.h>
#include <stdexcept>
#include <string>
class SocketException : public std::runtime_error {
private:
    int errorCode;
public:
    SocketException(const std::string& message, int errCode) 
        : std::runtime_error(message + " (Error code: " + std::to_string(errCode) + ")")
        , errorCode(errCode) {}
    int GetErrorCode() const { return errorCode; }
    static std::string GetErrorDescription(int errorCode) {
        LPSTR errorMsg = NULL;
        DWORD msgLength = FormatMessageA(
            FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
            NULL, errorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
            (LPSTR)&errorMsg, 0, NULL);
        std::string result;
        if (msgLength > 0) {
            result = std::string(errorMsg);
            LocalFree(errorMsg);
        } else {
            result = "Unknown error";
        }
        return result;
    }
};
// 使用示例
void SafeSocketConnect(SOCKET s, const sockaddr* addr, int addrlen) {
    if (connect(s, addr, addrlen) == SOCKET_ERROR) {
        int err = WSAGetLastError();
        throw SocketException("Connect failed", err);
    }
}

七、總結(jié)

通過(guò)本文的全面介紹,我們深入探討了WSAGetLastError()函數(shù)的各個(gè)方面。主要內(nèi)容包括:

7.1 核心知識(shí)點(diǎn)回顧

  • 錯(cuò)誤碼分類(lèi)體系:Windows Sockets錯(cuò)誤碼分為四大類(lèi),涵蓋從基礎(chǔ)系統(tǒng)錯(cuò)誤到高級(jí)網(wǎng)絡(luò)服務(wù)錯(cuò)誤。
  • 錯(cuò)誤碼范圍分布:核心Socket錯(cuò)誤碼主要在10000-11000范圍,名稱(chēng)服務(wù)錯(cuò)誤在11000-11100范圍。
  • 動(dòng)態(tài)獲取方法:使用FormatMessage等API可以動(dòng)態(tài)獲取錯(cuò)誤描述,避免硬編碼。
  • 錯(cuò)誤處理最佳實(shí)踐:立即保存錯(cuò)誤碼、使用統(tǒng)一的錯(cuò)誤處理框架、集成異常處理機(jī)制。

7.2 實(shí)用速查表

常見(jiàn)錯(cuò)誤碼處理建議

  • WSAENOTINITIALISED(10093):確保正確調(diào)用WSAStartup
  • WSAEADDRINUSE(10048):更換端口或設(shè)置SO_REUSEADDR
  • WSAECONNREFUSED(10061):檢查目標(biāo)服務(wù)狀態(tài)
  • WSAETIMEDOUT(10060):調(diào)整超時(shí)設(shè)置或檢查網(wǎng)絡(luò)狀況

7.3 進(jìn)一步學(xué)習(xí)方向

  • 深入研究重疊I/O錯(cuò)誤處理
  • 學(xué)習(xí)異步Socket操作的錯(cuò)誤處理模式
  • 掌握網(wǎng)絡(luò)編程中的異常安全設(shè)計(jì)
  • 了解跨平臺(tái)Socket編程的錯(cuò)誤處理差異

通過(guò)掌握WSAGetLastError()的全面知識(shí),開(kāi)發(fā)者可以構(gòu)建更加穩(wěn)定、可靠的網(wǎng)絡(luò)應(yīng)用程序,有效診斷和解決各種Windows Sockets編程中的問(wèn)題。

到此這篇關(guān)于C語(yǔ)言WSAGetLastError函數(shù)的文章就介紹到這了,更多相關(guān)C語(yǔ)言WSAGetLastError函數(shù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C++ 數(shù)據(jù)結(jié)構(gòu)二叉樹(shù)(前序/中序/后序遞歸、非遞歸遍歷)

    C++ 數(shù)據(jù)結(jié)構(gòu)二叉樹(shù)(前序/中序/后序遞歸、非遞歸遍歷)

    這篇文章主要介紹了C++ 數(shù)據(jù)結(jié)構(gòu)二叉樹(shù)(前序/中序/后序遞歸、非遞歸遍歷)的相關(guān)資料,這里提供實(shí)例代碼來(lái)幫助大家理解掌握二叉樹(shù),需要的朋友可以參考下
    2017-07-07
  • C++中智能指針最常用的shared_ptr和unique_ptr

    C++中智能指針最常用的shared_ptr和unique_ptr

    C++中的智能指針最常用的是shared_ptr和unique_ptr,C++新手最常問(wèn)的問(wèn)題是我從一個(gè)函數(shù)中拿到unique_ptr,但要轉(zhuǎn)成shared_ptr才能使用,要怎么轉(zhuǎn)換?同理是否能將shared_ptr轉(zhuǎn)換成unique_ptr,面對(duì)這些問(wèn)題,跟隨小編一起看看吧
    2022-08-08
  • C++基礎(chǔ)概念講述

    C++基礎(chǔ)概念講述

    這篇文章主要介紹了C++基礎(chǔ)概念,??本次為C++的一個(gè)開(kāi)篇,重點(diǎn)是更好的理解C++相對(duì)于其他編程語(yǔ)言的一個(gè)特性,之后會(huì)持續(xù)更新,本次專(zhuān)欄計(jì)劃是掌握C++的基礎(chǔ)語(yǔ)法以及常用特性,并且從細(xì)節(jié)上去理解,需要的朋友可以參考一下
    2021-12-12
  • C語(yǔ)言強(qiáng)制類(lèi)型轉(zhuǎn)換規(guī)則實(shí)例詳解

    C語(yǔ)言強(qiáng)制類(lèi)型轉(zhuǎn)換規(guī)則實(shí)例詳解

    強(qiáng)制類(lèi)型轉(zhuǎn)換是把變量從一種類(lèi)型轉(zhuǎn)換為另一種數(shù)據(jù)類(lèi)型,下面這篇文章主要給大家介紹了關(guān)于C語(yǔ)言強(qiáng)制類(lèi)型轉(zhuǎn)換的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-06-06
  • C++AVL樹(shù)4種旋轉(zhuǎn)詳講(左單旋、右單旋、左右雙旋、右左雙旋)

    C++AVL樹(shù)4種旋轉(zhuǎn)詳講(左單旋、右單旋、左右雙旋、右左雙旋)

    AVL樹(shù)即平衡二叉搜索樹(shù),平衡因子bf=右子樹(shù)的高度-左子樹(shù)的高度,bf為0,-1,1時(shí),此樹(shù)即平衡,下面這篇文章主要給大家介紹了關(guān)于C++AVL樹(shù)4種旋轉(zhuǎn)(左單旋、右單旋、左右雙旋、右左雙旋)的相關(guān)資料,需要的朋友可以參考下
    2022-11-11
  • C語(yǔ)言中函數(shù)返回值不一致問(wèn)題

    C語(yǔ)言中函數(shù)返回值不一致問(wèn)題

    這篇文章主要介紹了C語(yǔ)言中函數(shù)返回值不一致問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • 簡(jiǎn)單對(duì)比C語(yǔ)言中的fputs()函數(shù)和fputc()函數(shù)

    簡(jiǎn)單對(duì)比C語(yǔ)言中的fputs()函數(shù)和fputc()函數(shù)

    這篇文章主要介紹了簡(jiǎn)單對(duì)比C語(yǔ)言中的fputs()函數(shù)和fputc()函數(shù),注意其之間的區(qū)別,需要的朋友可以參考下
    2015-08-08
  • C語(yǔ)言例題之輸出1000以?xún)?nèi)的所有完數(shù)

    C語(yǔ)言例題之輸出1000以?xún)?nèi)的所有完數(shù)

    完數(shù)是一些特殊的自然數(shù),它所有的真因子(即除了自身以外的約數(shù))的和(即因子函數(shù)),恰好等于它本身,如果一個(gè)數(shù)恰好等于它的因子之和,則稱(chēng)該數(shù)為“完數(shù)”,這篇文章主要給大家介紹了關(guān)于C語(yǔ)言例題之輸出1000以?xún)?nèi)的所有完數(shù)的相關(guān)資料,需要的朋友可以參考下
    2022-11-11
  • QT使用SQLite數(shù)據(jù)庫(kù)超詳細(xì)教程(增刪改查、對(duì)大量數(shù)據(jù)快速存儲(chǔ)和更新)

    QT使用SQLite數(shù)據(jù)庫(kù)超詳細(xì)教程(增刪改查、對(duì)大量數(shù)據(jù)快速存儲(chǔ)和更新)

    這篇文章主要給大家介紹了關(guān)于QT使用SQLite數(shù)據(jù)庫(kù)的相關(guān)資料,其中包括增刪改查以及對(duì)大量數(shù)據(jù)快速存儲(chǔ)和更新,SQLite是一種嵌入式關(guān)系型數(shù)據(jù)庫(kù)管理系統(tǒng),它是一個(gè)軟件庫(kù),提供了一個(gè)自包含、無(wú)服務(wù)器、零配置的、事務(wù)性的SQL數(shù)據(jù)庫(kù)引擎,需要的朋友可以參考下
    2024-01-01
  • 淺析成員函數(shù)和常成員函數(shù)的調(diào)用

    淺析成員函數(shù)和常成員函數(shù)的調(diào)用

    下面小編就為大家?guī)?lái)一篇淺析成員函數(shù)和常成員函數(shù)的調(diào)用。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考,一起跟隨小編過(guò)來(lái)看看吧
    2016-05-05

最新評(píng)論

利津县| 内丘县| 错那县| 香格里拉县| 新田县| 镇康县| 黄浦区| 奉新县| 封开县| 临城县| 塘沽区| 南江县| 安西县| 邯郸县| 莎车县| 育儿| 乐都县| 岢岚县| 西城区| 乌鲁木齐市| 大丰市| 武安市| 湄潭县| 淮滨县| 凤阳县| 红桥区| 那曲县| 兰考县| 家居| 普格县| 竹山县| 晋中市| 嘉义县| 新龙县| 成武县| 巩留县| 富平县| 潜山县| 昌宁县| 新余市| 洛浦县|