【问题标题】:WinSock c++ inet_ntop always displays 204.204.204.204 (and accept() didn't failed)WinSock c++ inet_ntop 总是显示 204.204.204.204 (并且 accept() 没有失败)
【发布时间】:2023-11-03 00:40:01
【问题描述】:

我正在尝试制作一个 winsock 服务器,我想在他连接时在服务器上显示客户端的 ip,但这就是问题所在。每次我尝试连接它时都会显示 204.204.204.204。我试图与另一台计算机连接,但结果是一样的。 result in localhost

之后,我开始在这个网站上寻找和我有同样问题的人,我发现有几个人和我有同样的问题,但他们的 accept 或 inet_ntop 函数都不能正常工作。所以我检查了一下,这两个函数都没有返回错误。也许我很愚蠢,但我真的无法弄清楚问题出在哪里。 (顺便说一句,英语不是我的母语,所以请告诉我你是否注意到或者我的英语还不错)

不工作的代码部分

sockaddr_in from;
    int clientlen = sizeof(from);
    // accept
    SOCKET client = accept(server, (SOCKADDR*)&client, &clientlen);
    if (client == INVALID_SOCKET)
    {
        std::cout << "Error in accept(): " << WSAGetLastError << std::endl;
        WSACleanup();
    }
    else
    {

        char clientIp[17];
        if (inet_ntop(AF_INET, &from.sin_addr, clientIp, 17) == NULL)
        {
            std::cout << "Can't get the client's ip: " << WSAGetLastError() << std::endl;
        }

        std::cout << "ip connected: " << clientIp << std::endl;

如果你需要的话,完整的代码

#include <iostream>
#include <WinSock2.h>
#include <WS2tcpip.h>
#include <string>

#pragma comment(lib, "ws2_32.lib")

int main()
{
    std::cout << "--- Tcp/ip Server ---" << std::endl;
    WSADATA wsa;
    WSAStartup(MAKEWORD(2, 2), &wsa);

    SOCKET server = socket(AF_INET, SOCK_STREAM, 0);
    if (server == INVALID_SOCKET)
    {
        std::cout << "error in SOCKET(): "<< WSAGetLastError() << std::endl;
        WSACleanup();
    }
    sockaddr_in s;
    s.sin_family = AF_INET;
    s.sin_addr.s_addr = INADDR_ANY;
    s.sin_port = htons(52000);

    // bind
    if (bind(server, (sockaddr*)&s, sizeof(s)) == SOCKET_ERROR)
    {
        std::cout << "Error: bind()" << std::endl;
    }
    //listen
    if (listen(server, SOMAXCONN) == SOCKET_ERROR)
    {
        std::cout << "Error in listen(): " << WSAGetLastError() << std::endl;
        WSACleanup();
    }
    sockaddr_in from;
    int clientlen = sizeof(from);
    // accept
    SOCKET client = accept(server, (SOCKADDR*)&client, &clientlen);
    if (client == INVALID_SOCKET)
    {
        std::cout << "Error in accept(): " << WSAGetLastError << std::endl;
        WSACleanup();
    }
    else
    {

        char clientIp[17];
        if (inet_ntop(AF_INET, &from.sin_addr, clientIp, 17) == NULL)
        {
            std::cout << "Can't get the client's ip: " << WSAGetLastError() << std::endl;
        }

        std::cout << "ip connected: " << clientIp << std::endl;

        // the code isn't finished yet

        system("pause");
        WSACleanup();
    }
    return 0;
}

【问题讨论】:

  • accept 的第二个参数看起来不对。
  • 附带问题,您会很高兴知道,您的英语还不错。它并不完美,但大多数母语人士的英语也不是完美的,所以......
  • @1201ProgramAlarm 也许但是函数的返回值不等于 NULL 所以它应该是好的(我认为)。
  • @Chipster 哈哈谢谢!
  • 204.204.204.204 之类的东西应该会在你下次看到它时提醒你所有的警钟:204 是十六进制的。 0xcc。看看SO: In Visual Studio C++, what are the memory allocation representations? 看看我的意思。 ;-)

标签: c++ c networking winsock winsock2


【解决方案1】:

你在accept()的第二个参数中传递了错误变量的地址。

您正在传递您即将分配accept() 的结果的SOCKET client 变量的地址。 C++ 允许在同一语句中声明和初始化变量时获取变量的地址。但在这种情况下,这不是你想要的。您需要传递 sockaddr_in from 变量的地址:

sockaddr_in from;
int clientlen = sizeof(from);
// accept
SOCKET client = accept(server, (SOCKADDR*)&from, &clientlen); // <-- &from instead of &client

您的from 变量未初始化,并且您的编译器在调试模式下用0xCC(十进制204)字节填充未初始化的变量,这就是为什么您最终会看到204.204.204.204(十六进制0xCC 0xCC 0xCC 0xCCinet_ntop() 当你没有正确初始化你的 from 变量时。

【讨论】: