【问题标题】:Broadcasting UDP packet to 255.255.255.255将 UDP 数据包广播到 255.255.255.255
【发布时间】:2013-11-04 15:47:45
【问题描述】:

第一次发帖,希望这是一个简单的:

我需要向一个硬件发送一个广播数据包,当它启动时,它与我的机器位于不同的子网中,以便告诉它将其 IP 地址重置为我网络上的一个。但是,除非我使用 DHCP,否则我似乎无法从自己的子网广播,最终我将无法做到。网络上没有路由器,只是在我的机器和我要与之通话的机器之间进行简单的切换,再加上网络上的其他几台 Linux 机器。

所以基本上这个示例代码在测试环境中的 Fedora 19 上工作(在我启用了 DHCP 的较大网络上),直到我尝试静态设置我的 IP 地址:

int main(int argc, char *argv[])
{
    int sock;
    if( (sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
    {
        perror("socket : ");
        return -1;
    }

    int broadcast = 1;
    if( setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof(broadcast)) != 0 )
    {
        perror("setsockopt : ");
        close(sock);
        return -1;
    }

    char *ip = "255.255.255.255";
    char * msg = "Hello World!";

    struct sockaddr_in si;
    si.sin_family = AF_INET;
    si.sin_port   = htons( 4444 );
    inet_aton( ip, &si.sin_addr.s_addr );

    /* send data */
    size_t nBytes = sendto(sock, msg, strlen(msg), 0, 
                    (struct sockaddr*) &si, sizeof(si));

    printf("Sent msg: %s, %d bytes with socket %d to %s\n", msg, nBytes, sock, ip);

    return 0;
}

如果我使用的是 DHCP,则输出为:

Sent msg: Hello World!, 12 bytes with socket 3 to 255.255.255.255

我可以看到数据包在 Wireshark 中发出。

如果我将我的 IP 静态设置为 192.168.100.1,我会得到:

Sent msg: Hello World!, -1 bytes with socket 3 to 255.255.255.255

而且我在 Wireshark 中看不到数据包。而且我可以确认 ifconfig 中显示的 TX 数据包数量不会增加。我尝试禁用防火墙:

sudo iptables -F

但这并没有做任何事情。有人看到我缺少的东西吗?我可以广播到 192.168.100.255,但这不会到达我需要与之交谈的框,例如默认情况下可能在 192.168.200.10、255.255.255.0。我可以通过更改网络上其他所有设备的网络参数来使其工作,但这并不是一个真正的选择。

编辑: 关于一些 cmets 和答案,请注意我没有使用路由器,并且可以在我的计算机和另一个盒子之间只用一根电线复制行为。所以,真正的问题是,为什么 Linux 不发送数据包?我显然不知道,但我怀疑 Linux 本身会丢弃跨子网广播数据包,除非它可以将该决定委托给网络上的另一个权威。无论如何,鉴于我的网络是如此之小,我只需要解决它。

【问题讨论】:

  • 您是否将setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof(broadcast) 中的设置调整为不广播?
  • 你能打印出 errno,或者如果 sendto() 函数失败,至少做一个perror("sendto"),那会提供更多的 h
  • “DHCP”是一种非常特殊的广播,因为路由器充当中继代理并将 DHCP“消息”再次广播到其他子网。如此处所述:en.wikipedia.org/wiki/Dhcp“最初,同一子网上的 DHCP 客户端和服务器通过 UDP 广播进行通信。如果客户端和服务器位于不同的子网上,则可以使用 DHCP 帮助程序或 DHCP 中继代理。客户端请求更新现有的租约可以直接通过 UDP 单播进行通信,因为此时客户端已经建立了 IP 地址。”
  • 谢谢,我应该检查一下原帖中的errno。 perror("sendto") 打印出“网络无法访问”。这对我来说没有意义——我知道路由器要做的负责的事情是丢弃数据包,但由于没有路由器,我会想象我的交换机上的任何东西都能够接收数据包。
  • @GPHoit 是连接路由器的交换机吗?

标签: linux networking network-programming udp dhcp


【解决方案1】:

我刚刚遇到了这个问题。在我移除网关之前一切正常,然后在尝试从套接字发送时出现网络无法访问错误。

由于我使用广播消息来配置我的盒子的网络设置,因此我无法配置网关地址以使其正常工作。但是,由于我的盒子只有一个网络接口,我找到了以下解决方案:

// Bind to the proper interface to be able to send without default gateway char netif[] = "eth0"; setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, netif, sizeof(netif));

有了这个,无论任何默认网关如何,我都可以发送到套接字上的广播 255.255.255.255 地址。只要您知道要使用哪个接口,此解决方案就应该适用于多个网络接口。

【讨论】:

  • 我最近从 Red Hat 6 升级到 Red Hat 7 后遇到了这个问题。原来旧版 linux 在路由表中配置了默认路由。较新的不会自动配置此路由。我的解决方法是输入:#route add default
【解决方案2】:

根据定义,广播仅限于一个子网。看到广播逃离一个人的子网并溢出互联网将是可怕的。如果您正在寻找一种跨子网的方法,您应该查看Multicast。还要检查this。祝你好运!

【讨论】:

  • OP 只是发送到 255.255.255.255。但 sendto() 失败。这应该正常工作。还要记住,如果你们都在同一个第 2 层广播域上,则可以广播到不同的 IP 子网(您永远不应该这样做,但 OP 描述他实际上是)。
  • 嗯。我有点困惑。他提到使用广播到达不同子网上的硬件。然而,他继续发布了一个代码,这显然在更改 IP 地址时并没有起到应有的作用。无论如何,除非他有一个特殊的路由器(cisco ...),否则预期的广播不会通过路由器,他可以配置它来这样做。
  • @ nos:我相信如果子网掩码是 255.255.0.0(B 类),情况就是这样。但他在 C 类网络上。所以广播到 192.168.100.255 会到达 192.168.100.X 但不会到达 192.168.200.10
  • 是的,但他正在使用广播地址 255.255.255.255,这 afaik,你应该能够在 linux 中做到 - 而且他没有路由器。这意味着例如您使用 1 个哑以太网交换机,将 1 台 PC 连接到它,例如 192.168.100.0/24 和 1 台 PC,它位于 192.168.200.0/24。这 2 台 PC 现在位于同一个以太网广播域中,并且应该能够看到 eachouters 向 255.255.255.255 广播数据包。 (他们甚至可以看到(至少使用wireshark)广播到192.168.100.255或192.168.200.255的每个人,尽管它们通常会被网卡过滤掉。)
  • 感谢两位cmets。你是正确的 hhachem 我没有包含任何代码来重置硬件的网络参数,这只是一个简单的程序,就网络端而言,它有效地做同样的事情,没有提到该硬件的实际接口在这里。
【解决方案3】:

请检查您的默认网关。如果网关的 IP 在另一个子网中,您将收到错误“网络无法访问”。在向 255.255.255.255 地址广播一段时间后,顺便直接发送到子网广播(例如,如果您的 ip 为 192.168.1.1,则为 192.168.1.255)即使网关 IP 在另一个子网中也可以正常工作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-05-22
    • 2017-12-04
    • 2018-05-29
    • 2019-04-19
    • 2014-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多