【问题标题】:Winsock socket doesn't recveive packet cppWinsock 套接字不接收数据包 cpp
【发布时间】:2021-02-19 21:51:21
【问题描述】:

我有一个客户端,它等待服务器向特定端口发送广播,然后返回消息。

我可以在 Wireshark 中看到数据包,但我的应用程序没有捕获它。

这是捕获数据包的函数。 (getPrivateIP 有效)

uint32_t findMastersIP()
{
    sockaddr_in recvAddr{};
    sockaddr_in sendAddr{};

    SOCKET s = socket(AF_INET, SOCK_DGRAM, 0);
    if (s == INVALID_SOCKET)
        std::cout << "Socket error <" << WSAGetLastError() << ">" << std::endl;
    
    int opt;

    std::string message, response;
    char* buf = new char[65536];
    int fromlen;

    recvAddr.sin_addr.s_addr = getPrivateIP();
    recvAddr.sin_port = htons(667);
    recvAddr.sin_family = AF_INET;

    fromlen = sizeof(recvAddr);

    opt = 1;
    if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const char*)&opt, sizeof(opt))<0)
        std::cout << "Sockopt error <" << WSAGetLastError() << ">" << std::endl;

    if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, (const char*)&opt, sizeof(opt)) < 0)
        std::cout << "Sockopt error <" << WSAGetLastError() << ">" << std::endl;

    if(bind(s, (sockaddr*)&recvAddr, sizeof recvAddr) < 0)
        std::cout << "Bind error <" << WSAGetLastError() << ">" << std::endl;

    /*fixed messages for my "protocol"*/
    message = "What is your IP?";
    response = "My IP";

    /*wait for the master to ask me to connect*/
    do {
        ZeroMemory(buf, 65536);
        if(recvfrom(s, buf, 65536, 0, (sockaddr*)&recvAddr, &fromlen) <= 0)
        {
            std::cout << "Recieve error <" << WSAGetLastError() << ">" << std::endl;
            goto errorLable;
        }
        std::cout << buf << std::endl;
    } while (!std::string(buf)._Equal(message));

    if(sendto(s, response.c_str(), response.size(), 0, (sockaddr*)&recvAddr, sizeof(recvAddr)) <= 0)
        std::cout << "Send error <" << WSAGetLastError() << ">" << std::endl;


errorLable:
    delete[] buf;
    closesocket(s);
    return recvAddr.sin_addr.s_addr;
}

奇怪的是,当服务器和客户端在同一台计算机上时它可以工作,但当它们在两台不同的计算机上时就不行。

有人知道是什么原因造成的吗?以及如何解决?

【问题讨论】:

  • 战术说明:如果你将do/while循环和随后的if移动到一个函数中,当你收到错误或消息时将return从函数中移动,你赢了'在代码审查期间不必浪费时间与goto 语句争吵。
  • recvAddr.sin_addr.s_addr = getPrivateIP(); 看起来您只接受来自getPrivateIP 返回的任何消息。因为我不知道它返回什么,所以我不能确定这是否是你想要的,但如果不是,你会得到你所看到的行为。
  • 它返回我的ip,“10.0.0.8”,它不会接受广播消息吗?
  • 我在广播方面很弱,从未尝试将广播消息侦听器绑定到单个发件人,所以我可能大错特错,但通常如果您绑定到特定地址,您只接受来自该地址的消息地址。如果您不在乎是谁在发送消息,请使用 INADDR_ANY
  • @LeoSegol 与您的问题无关:您不需要SO_BROADCAST接收广播,只需发送广播。在调用recvfrom() 之前,您的循环不会在每次迭代中重置fromlenrecvfrom() 返回 0 不是错误情况。 buf 不保证是空终止的,除非发送方正在发送空终止数据,使用recvfrom() 的返回值知道buf 的实际长度。 std::string 没有 _Equal() 方法,请改用其 operator==compare() 方法。调用 `sendto(

标签: c++ udp winsock2


【解决方案1】:

我发现了问题,防火墙出于某种原因阻止了我在私有网络中的程序。我现在已经启用了这个程序,它运行良好。

【讨论】:

  • 就我的一般知识而言,在使用recvAddr.sin_addr.s_addr = getPrivateIP(); 进行防火墙配置之后,它是否适用于防火墙配置?如果我发现自己不得不这样做,很高兴知道绑定地址的处理方式是否不同。
  • @user4581301 我不确定我是否理解您的问题。我使用getPrivateIP() 而不是INADDR_ANY,它工作得很好。
  • 这回答了我的问题。谢谢你。出乎意料。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-25
  • 2013-03-23
  • 1970-01-01
  • 2020-09-24
  • 2012-04-23
  • 1970-01-01
相关资源
最近更新 更多