【问题标题】:winsock: connect fails with error 10049 when using localhost (127.0.0.1)winsock:使用 localhost (127.0.0.1) 时连接失败并出现错误 10049
【发布时间】:2012-08-15 13:22:58
【问题描述】:

我写了一个类来封装一些winsock函数来模拟一个简单的TCP套接字来满足我的需要......

当我尝试运行简单的连接并发送数据到服务器测试时,“客户端”在调用连接时失败,错误代码为 10049 (WSAEADDRNOTAVAIL) connect function on MSDN

我正在做的是(下面的代码): 服务器:

  1. 创建服务器套接字 -> 将其绑定到 端口 12345
  2. 将 Socket 置于监听模式
  3. 接听电话

客户

  1. 创建套接字 -> 将其绑定到随机端口
  2. 调用 Connect:连接到 localhost,端口 12345

=> 如上所述,连接调用失败并出现错误 10049

这里是包含“服务器”的主要功能:

HANDLE hThread = NULL;
Inc::CSocketTCP ServerSock;
Inc::CSocketTCP ClientSock;

try
{

    ServerSock.Bind(L"", L"12345");
    ServerSock.Listen(10);

    //Spawn the senders-thread
    hThread = (HANDLE)_beginthreadex(nullptr, 0, Procy, nullptr, 0, nullptr);

    //accept
    ServerSock.Accept(ClientSock);


    //Adjust the maximum packet size
    ClientSock.SetPacketSize(100);


    //receive data
    std::wstring Data;
    ClientSock.Receive(Data);

    std::wcout << "Received:\t" << Data << std::endl;
}
catch(std::exception& e)
{...

客户端线程函数

unsigned int WINAPI Procy(void* p)

{

Sleep(1500);
try{
    Inc::CSocketTCP SenderSock;
    SenderSock.Bind(L"", L"123456");

    SenderSock.Connect(L"localhost", L"12345");


    //Adjust packet size
    SenderSock.SetPacketSize(100);

    //Send Data
    std::wstring Data = L"Hello Bello!";
    SenderSock.Send(Data);
}
catch(std::exception& e)
{
    std::wcout << e.what() << std::endl;
}...

连接功能

    int Inc::CSocketTCP::Connect(const std::wstring& IP, const std::wstring& Port)
{
    //NOTE: assert that the socket is valid
    assert(m_Socket != INVALID_SOCKET);

    //for debuggin: convert WStringToString here
    std::string strIP = WStringToString(IP), strPort = WStringToString(Port);

    Incgetaddrinfo AddyResolver;
    addrinfo hints = {}, *pFinal = nullptr;

    hints.ai_family = AF_INET;

    //resolve the ip/port-combination for the connection process
    INT Ret = AddyResolver(strIP.c_str(), strPort.c_str(), &hints, &pFinal);
    if(Ret)
    {
        //error handling: throw an error description
        std::string ErrorString("Resolving Process failed (Connect): ");
        ErrorString.append(Inc::NumberToString<INT>(Ret));
        throw(std::runtime_error(ErrorString.c_str()));
    }


    /*---for debbuging---*/
    sockaddr_in *pP = (sockaddr_in*)(pFinal->ai_addr);
    u_short Porty = ntohs(pP->sin_port);
    char AddBuffer[20] = "";

    InetNtopA(AF_INET, (PVOID)&pP->sin_addr, AddBuffer, 20);
    /*--------------------------------------------------------*/


    if(connect(m_Socket, pFinal->ai_addr, pFinal->ai_addrlen) == SOCKET_ERROR)
    {
        int ErrorCode = WSAGetLastError();
        if((ErrorCode == WSAETIMEDOUT) || (ErrorCode == WSAEHOSTUNREACH) || (ErrorCode == WSAENETUNREACH))
        {
            //Just Unreachable
            return TCP_TARGETUNREACHABLE;
        }

        //real errors now
        std::string ErrorString("Connection Process failed: ");
        ErrorString.append(Inc::NumberToString<int>(ErrorCode));
        throw(std::runtime_error(ErrorString.c_str()));
    }

    return TCP_SUCCESS;
}

其他信息: -Incgetaddrinfo是一个封装getaddrinfo的函数对象... - 使用调试器单步执行或让它们单独运行时,没有任何服务器函数返回任何错误并按预期工作......

我很高兴听到您的建议,问题可能是什么...

编辑:当我连接到("localhost","12345")连接到("",12345)... 查看getaddrinfo 的地址解析过程时,它为"localhost" 提供127.0.0.1,为"" 提供我的真实IP

为什么它不适用于我的环回 IP?

【问题讨论】:

    标签: c++ windows sockets winsock connect


    【解决方案1】:

    你的问题有答案:

    ...它为"localhost" 提供127.0.0.1,为"" 提供我的真实IP

    这意味着您的服务器绑定到接口的真实 IP 而不是INADDR_ANY,即它不监听环回。

    编辑 0:

    创建侦听套接字时,您实际上并不需要名称解析。只需将bind() 发送到INADDR_ANY 即可监听所有可用接口(包括环回)。

    【讨论】:

    • 但我确实尝试过绑定到本地主机,客户端也无法连接...我也尝试停用 Windows 防火墙...
    • netstat -na 将显示在哪些地址上正在监听哪些端口。 Windows 上的 IIRC -b 选项将显示哪些程序使用哪些连接。
    • 好的...当我绑定到“”(INADDR_ANY,因为 getaddrinfo 提示中的 AI_PASSIVE)它绑定到 192 ..... 并正在使用端口 12345 监听该 IP(netstat -na) => 尝试通过 "" 连接有效,但 localhost 失败...将服务器套接字绑定到 localhost 使其监听 127.0.0.1 (netstat) => 通过 "" 连接失败,并且通过 localhost 也失败.. .
    • "Dude",是的,我做到了 - 如上所述 - 通过将空字符串传递给 getaddrinfo 并使用标志 AI_PASSIVE (msdn.microsoft.com/en-us/library/ms738520(v=vs .85) => 向下到标志位表)
    • 好的,找到了问题...当使用名称解析时,似乎将“”传递给 getaddrinfo 不再像以前那样工作了,或者它在过去对我来说很幸运...你必须通过 NULL/nullptr,它才能工作......使用 (strIP.empty()?nullptr : strIP.c_str()) 添加了这个,感谢您的帮助和耐心!
    【解决方案2】:

    在我的例子中,这个错误是由于在分配给address.sin_addr.s_addr之前没有在INADDR_LOOPBACK上调用htonl引起的。

    确保您转换为网络字节顺序,否则您将获得0x0100007f (1.0.0.127) 而不是0x7f000001 (127.0.0.1) 作为您的环回地址,并且绑定将失败并显示代码10049 (WSAEADDRNOTAVAIL)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-27
      • 2021-12-19
      • 2020-04-21
      • 2020-01-21
      相关资源
      最近更新 更多