Winsock 连接因 WSAEFAULT 失败 |仅 Windows 11 出错

Winsock connect fails with WSAEFAULT | Error on Windows 11 only

我的代码完美适用于从 XP 到 10 的任何 Windows。 现在我第一次在 Win11 中测试了我的代码, 并且 connect() 函数失败并出现错误 10014 WSAEFAULT:

Bad address. The system detected an invalid pointer address in attempting to use a pointer argument of a call. This error occurs if an application passes an invalid pointer value, or if the length of the buffer is too small. For instance, if the length of an argument, which is a sockaddr structure, is smaller than the sizeof(sockaddr).

然而,当我检查我的调试器时,sockaddr_in 结构似乎被正确传递:

connect(hSocket, (sockaddr*)(&InSockAddr), sizeof(InSockAddr))

我正在使用 Visual C++ 2015 编译器。

这里是相关代码的片段:

#include <WinSock2.h>

class CConnection
{
   public:
    static bool         bWinsockInitialized;
    SOCKET              hSocket = INVALID_SOCKET;
    sockaddr_in         sockAddr;
         
    bool                Create();
    bool                InitializeWinsock();
    bool                Connect(sockaddr_in &InSockAddr);
};   

CConnection sckt_Main;
sockaddr_in g_sockAddr;


void main()
{
    if (!sckt_Main.Create())
    {
        // Error: Unable to create connection socket
        return;
    }

    g_sockAddr.sin_family = AF_INET;

    // Get IP address from string. 
    // If address is a DNS, HostInfo->h_addr will contain resolved IP address.
    // Save host information into HostInfo struct:
    hostent* HostInfo = gethostbyname("127.0.0.1");

    //Error checking:
    if (!HostInfo) {
        return;
    }

    assert((sizeof(g_sockAddr.sin_addr)) >= HostInfo->h_length);

    //Copy the resolved IP address into our sockAddr structure: 
    memcpy(&g_sockAddr.sin_addr, HostInfo->h_addr, HostInfo->h_length);

    //Saves connection port
    g_sockAddr.sin_port = htons(atoi("2405"));
    
    sckt_Main.Connect(g_sockAddr);
}


bool CConnection::Create()
{
    if (!InitializeWinsock()) {
        return false;
    }
        
    hSocket = socket(AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP);
        
    if (this->hSocket == INVALID_SOCKET) 
        return false;
        
    return true;
}


bool CConnection::InitializeWinsock()
{
    WSADATA wsaData;
    if (!WSAStartup(MAKEWORD(2, 2), &wsaData)) {
       bWinsockInitialized = true;
    } 
    else bWinsockInitialized = false;
        
    return bWinsockInitialized;
}


bool CConnection::Connect(sockaddr_in &InSockAddr)
{

    // If no error occurs, connect returns zero. 
    // Otherwise, it returns SOCKET_ERROR, and a specific error code can be retrieved by calling WSAGetLastError.
    if (connect(hSocket, (sockaddr*)(&InSockAddr), sizeof(InSockAddr)) == 0)
    {
       // Connect SUCCESS
       return true;
    }
    else 
    {   
       // !!! connect error !!!
       int err = WSAGetLastError();
       return false;
    }
}

如评论中所述,您的代码不支持 IPv6。 Windows 11 默认启用 IPv6。

您应该将您的代码更新为与 IPv4 和 IPv6 无关。

Microsoft Docs

请注意,微软 checkv4.exe 很久以前就停止发货了,但是如果我 运行 它违反了您的代码,我会得到:

sockaddr_in : use sockaddr_storage instead, or use sockaddr_in6 in addition for IPv6 support

AF_INET : use AF_INET6 in addition for IPv6 support

gethostbyname : use getaddrinfo instead

hostent : use addrinfo instead