接收UDP广播

11

我需要接收UDP广播(如果有区别的话,在Ubuntu上)。使用Wireshark,我可以看到数据包从服务器机器发送,我也可以看到客户端机器接收到它,但我的程序完全不知道。这是我拥有的:

sockaddr_in si_me, si_other;
int s;
assert((s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))!=-1);
int port=6000;
int broadcast=1;

setsockopt(s, SOL_SOCKET, SO_BROADCAST,
            &broadcast, sizeof broadcast);

memset(&si_me, 0, sizeof(si_me));
si_me.sin_family = AF_INET;
si_me.sin_port = htons(port);
si_me.sin_addr.s_addr = INADDR_ANY;

assert(::bind(s, (sockaddr *)&si_me, sizeof(sockaddr))!=-1);

while(1)
{
    char buf[10000];
    unsigned slen=sizeof(sockaddr);
    recvfrom(s, buf, sizeof(buf)-1, 0, (sockaddr *)&si_other, &slen);

    printf("recv: %s\n", buf);
}

在调试模式下编译,断言在编译期间没有被删除,我的程序在 recvfrom 上一直阻塞。

除了这个,我还需要做什么才能接收到未定向的UDP广播吗?

编辑:再多提供一点信息,我将两台计算机连接到专用交换机上,没有外界干扰。我的客户端电脑上还有第二张网卡连接公司网络,也正常工作。

我可以ping通外部(互联网)和我的服务器机器(同时我可以在Wireshark中看到实际的数据包),但你永远不知道可能会出现什么问题。


这段代码经过轻微修改后,对我来说是可行的(以便宜C编译器编译)。可能bind绑定到了错误的接口?在客户端机器上执行netstat -an | grep 6000会返回什么? - Sean Bright
是的,它本应该工作,但对我来说不起作用。 "netstat -an" 没有显示开放的 6000 端口,我已经反复检查过了(我还尝试使用“重用” UDP 标志)。 - Blindy
bind() 方法实际上并没有打开端口,只有 connect()listen() 方法才能做到。但是你不需要通过 listen() 方法打开端口来接收 UDP 广播。 - Remy Lebeau
由于 UDP 是无连接的,因此在 UDP 套接字上调用 connect() 仅在套接字句柄内部建立本地和远程 IP/Port 对之间的静态关联,仅此而已。当我提到 connect() 打开一个端口时,我是指 TCP。在 UDP 套接字上调用 bind() 将绑定的 IP/Port 添加到 netstat 列表中,但不显示任何状态,这可能适用于所有 UDP 连接。 - Remy Lebeau
@RemyLebeau 这些都是非常不准确的。在UDP和TCP协议中,如果套接字从未进行绑定,connect()函数会执行一个bind()操作,并且这里是打开端口的位置,但并不是在connect()函数本身中。无论是隐式还是显式地进行绑定,UDP端口一旦出现就会在netstat中显示出来。netstat没有显示UDP状态:该端口要么打开,要么关闭。 - user207421
显示剩余2条评论
2个回答

4

事实证明,我的代码完全没有问题,正如我所想的那样。问题出在网络设置上。

为了记录下来,我已经在一个专用的集线器上设置了两台静态IP计算机,而不是使用服务器机器上内置的DHCP服务器来分配另一台计算机的IP地址。这对于我的问题来说相当局限,但你永远不知道...


-1

发送和接收广播

  1. 确保子网掩码的正确性。在Windows中,广播数据包的掩码无关紧要,但在Linux中不是如此。

  2. 将套接字绑定到INADDR_ANY

  3. 使用setsockopt设置为BROADCAST

  4. 调用sendto,并设置sendaddr.sin_addr.s_addr = inet_addr("your_interface_broadcast_address"), 或者 - 对于每个接口调用多次sendto,分别使用其广播IP地址。

  5. 调用recvfrom。在调用recvfrom之前,随时设置好长度参数。


10
为什么要发布这个?你可以看到我在2012年的原始留言中已经完全做到了这一点... - Blindy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接