【问题标题】:Receiving broadcast packet addressed to 255.255.255.255 in C++在 C++ 中接收地址为 255.255.255.255 的广播数据包
【发布时间】:2014-03-04 06:38:47
【问题描述】:

我有一个设备,它通过向端口 4930 上的 255.255.255.255 发送广播数据包而被发现,并且设备通过向端口 4930 上的 255.255.255.255 发送数据包来响应。

我有一个 C++ 代码的 sn-p 代码,它可以在端口 4930(源端口和目标端口)上向 255.255.255.255 发送数据包,但它无法从广播地址 255.255.255.255 接收数据包。

我可以看到设备工作正常,wireshark 可以看到来回的数据包,并且设备随附的专有软件可以很好地发现设备,问题出在 C++ 程序,所以请继续关注您的主题回复。

现在,正如我所说,我可以发送一个数据包,但首先我无法绑定到 IP 地址 255.255.255.255 来接收数据包。我可以将多播地址更改为 239.255.255.250 并且套接字将绑定,但我需要地址 255.255.255.255。

我的sn-p代码如下,我用的是VC++2010

bool CPTUProgramDlg::FindPTU(u_short port, const char * Destaddress){
    {
        //Data to send
        char packet_data[10] = {0x44,0x43,0x55,0x44,0x5f,0x50,0x49,0x4e,0x47,0x00};
        int packet_size=10;

        SOCKET sock;
        struct sockaddr_in addr;

        sock = socket(AF_INET, SOCK_DGRAM, 0);

        // set SO_BROADCAST on a socket to true (1): (so we can transmit to 255 addr)
        //In order to use broadcast the options of socket must change
        char broadcastON = 1;
        setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &broadcastON, sizeof broadcastON);

        if (sock < 0)
            return false;

        addr.sin_family = AF_INET;
        addr.sin_port = htons(port);
        addr.sin_addr.s_addr = inet_addr(Destaddress); // Specify dest IP

        sendto(sock, packet_data, packet_size, 0, (struct sockaddr*)&addr, sizeof(addr));

        if (bind(sock,(struct sockaddr*) &addr,sizeof(addr)) != -1){
            char Buff[512];
            recv(sock,Buff,512,0);
        }

        closesocket(sock);
    }

    return 1;
}

Wireshark 截图证明数据包正在发送:

【问题讨论】:

  • 尝试在 0.0.0.0 上绑定并按目标 IP 地址执行过滤。例如。通过使用 recvfrom 而不是 recv...
  • 顺便说一句。这种类型的数据包是广播的,而不是多播的。我从您的屏幕截图中看到,设备从端口 4930 响应端口 4930 - 您可能还需要使用两个不同的套接字 - 一个用于发送,一个用于接收。
  • 在0.0.0.0上绑定成功但是recvfrom返回-1,我添加的代码是sockaddr * from = new sockaddr[1]; if (recvfrom(sock,Buff,512,0,from,(int*)sizeof(sockaddr))
  • 啊,好吧,我刚刚查看了我的代码,它清楚地显示广播,不知道我是如何混淆广播和多播的:/感谢提示 bbonev!我会尝试初始化两个不同的套接字,看看会发生什么......
  • 优秀的Bbonev!那个模组效果很好!!谢谢大佬!!问题是绑定到 0.0.0.0 而不是 255.255.255.255 并使用单独的套接字,就像你说的那样!

标签: c++ c sockets networking


【解决方案1】:

从 wireshark 的输出中可以看出,特殊设备正在使用广播进行通信,并将使用与源和目标相同的端口号。

正常的套接字通信需要使用匹配的端口号,但广播消息不能在同一个套接字上交换,尤其是当端口号与使用wireshark 看到的不匹配时。

在 255.255.255.255 (INADDR_BROADCAST) 上的绑定通常应该有效,但可能会受到您的操作系统特权和权限的限制。

您可以尝试通过使用两个套接字来解决问题 - 一个用于接收,一个用于发送。当然,必须首先设置监听套接字并绑定到 0.0.0.0 (INADDR_ANY) 和端口 4930。在这种情况下,没有简单的方法可以按目标地址进行过滤(因为我在评论中写错了),因为大多数标准套接字 API 不提供从套接字获取目标地址的方法。在 Linux 上有一个例外 - IP_PKTINFO SOL_IP...

通过使用 recvfrom,您将获得响应设备的源单播地址。您必须注意,如果您的网络上有不止一台这样的设备,您将收到不止一个响应。

【讨论】:

    猜你喜欢
    • 2019-04-19
    • 1970-01-01
    • 1970-01-01
    • 2013-05-22
    • 1970-01-01
    • 2014-05-17
    • 2019-09-22
    • 2023-03-23
    相关资源
    最近更新 更多