请教大佬一个 Linux 组播的问题

2022-01-04 18:11:10 +08:00
 yaron

Linux 下组播接收不到其他 IP 的数据。 不知道是不是程序代码哪里出错了,但在其他嵌入式机子上运行过是正常的.. ...

情况:

  1. 机器 A 组播发送正常,其他 ip 能接受到机器 A 的数据
  2. 机器 A 组播接收失败,只能接收到自己发出去的数据,收不到其他 IP 组播发送的数据
  3. 其他 IP 直接单播发送给机器 A ,A 能接收到

具体实现流程:

  1. 创建套接字

    #define UDP_MCAST_PORT 36000        //组播端口
    #define UDP_MCAST_ADDR "224.0.1.88" //组播地址
    
    auto socket = socket(AF_INET,SOCK_DGRAM,0);
    if (socket <= 0)
    return false;
    
  2. 设置端口复用

    int opt = 1;
    if (setsockopt(socket, SOL_SOCKET, SO_REUSEADDR ,(char*)&opt, sizeof(opt)) < 0)
    	return false;
    
  3. 绑定组播端口

    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(UDP_MCAST_PORT);
    addr.sin_addr.s_addr = htonl(INADDR_ANY);
    
    if (bind(socket, (struct sockaddr*)&addr, sizeof(addr)) < 0)
    	return false;
    
  4. 加入组播

    struct ip_mreq mreq;
    mreq.imr_multiaddr.s_addr = inet_addr(UDP_MCAST_ADDR);
    mreq.imr_interface.s_addr = htonl(INADDR_ANY);
    
    if (setsockopt(socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&mreq, sizeof(mreq)) < 0)
    	return false;
    
  5. 发送与接收

    //发送
    struct sockaddr_in addrSrv;
    addrSrv.sin_family=AF_INET;
    addrSrv.sin_addr.s_addr = inet_addr(UDP_MCAST_ADDR);
    addrSrv.sin_port=htons(UDP_MCAST_PORT);
    
    if (sendto(socket, data, dataLen, 0, (struct sockaddr *)&addrSrv,sizeof(addrSrv)) > 0)
    	return true;
    
    //接收
    struct sockaddr_in group_addr;
    socklen_t addr_len = sizeof(group_addr);
    
    int len = recvfrom(socket, buff, buffLen, 0, (struct sockaddr *) &group_addr, (int *)&addr_len);
    recvIP = inet_ntoa(group_addr.sin_addr);
    recvPort = group_addr.sin_port;
    
903 次点击
所在节点    问与答
8 条回复
bitdepth
2022-01-04 18:23:04 +08:00
loop interface 有關閉?
IF_MULTICAST_IF 是不是沒設置?
ThinkZ
2022-01-04 18:30:06 +08:00
A 机多网卡?
yaron
2022-01-04 18:34:36 +08:00
@bitdepth 只有一张网卡,IF_MULTICAST_IF 是必须要设置的吗?请问下 loop interface 的作用是什么?我没配过这个参数,是指 IP_MULTICAST_LOOP 吗?
yaron
2022-01-04 18:34:53 +08:00
@ThinkZ 没有,只有一张网卡
bitdepth
2022-01-05 12:12:20 +08:00
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
這句就是問題了,組播接受必綁網路卡位置,因為多張網路卡可加入同一組播組,但是物理上不同的網路
yaron
2022-01-07 09:20:40 +08:00
@bitdepth 我后面也有试过多网卡的程序,但还是接收不到组播数据。程序如下,将第 4 步骤改为:
yaron
2022-01-07 09:21:09 +08:00
@bitdepth 1. 加入组播

```c++
struct ip_mreq mreq;
mreq.imr_multiaddr.s_addr = inet_addr(UDP_MCAST_ADDR);
mreq.imr_interface.s_addr = htonl(INADDR_ANY);

//指定接口接收组播信息
mreq.imr_interface.s_addr = inet_addr(localIP);

if (setsockopt(socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&mreq, sizeof(mreq)) < 0)
return false;
```

2. 指定组播出口网卡

```c++
struct in_addr addr;
memset(&addr, 0, sizeof(struct in_addr));

addr.s_addr=inet_addr(localIP);
if (setsockopt(socket, IPPROTO_IP, IP_MULTICAST_IF, (char*)&addr, sizeof(addr)) < 0)
return false;
```
bitdepth
2022-01-07 12:35:15 +08:00
代碼貼全吧,才有辦法批改

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/826173

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX