C++ 使用c+在RHEL 7上接收多播数据+;

C++ 使用c+在RHEL 7上接收多播数据+;,c++,sockets,udp,multicast,rhel,C++,Sockets,Udp,Multicast,Rhel,我试图在RHEL 7.2的网络接口上接收多播UDP数据 关于我的设置: 网卡:英特尔X540 IP:192.168.42.100 发行版:RHEL 7.2 多播地址:224.5.6.7 港口:2002年 接口名称:ens4f1 我打开了两个接口,Mobo上的1 Gbit和intel卡上的10 Gbit中的一个 像许多其他帖子一样,我的数据在wireshark和tcpdump上都可以看到,但是我的recvfrom调用挂起了。我的代码是所描述的类似问题的副本,该问题似乎适用于OP 注意事项: 1)

我试图在RHEL 7.2的网络接口上接收多播UDP数据

关于我的设置: 网卡:英特尔X540 IP:192.168.42.100 发行版:RHEL 7.2 多播地址:224.5.6.7 港口:2002年 接口名称:ens4f1

我打开了两个接口,Mobo上的1 Gbit和intel卡上的10 Gbit中的一个

像许多其他帖子一样,我的数据在wireshark和tcpdump上都可以看到,但是我的recvfrom调用挂起了。我的代码是所描述的类似问题的副本,该问题似乎适用于OP

注意事项:

1) 我以root用户身份运行代码

2) 我已尝试将/proc/sys/net/ipv4/conf/ens4f1/rp_过滤器中的rp_过滤器更改为0。不变

3) 禁用SELinux并没有改变任何事情

4) Wireshark和tcpdump可以很好地显示数据。如下所示

[@localhost ~]$ sudo tcpdump -c 5 -i ens4f1 -v
tcpdump: listening on ens4f1, link-type EN10MB (Ethernet), capture size 65535 bytes
15:43:57.368470 IP (tos 0x0, ttl 255, id 6526, offset 0, flags [DF], proto UDP (17), length 7996)
    192.168.42.44.62111 > 224.5.6.7.globe: UDP, length 7968
15:43:57.368477 IP (tos 0x0, ttl 255, id 6526, offset 0, flags [DF], proto UDP (17), length 316)
    192.168.42.44.62111 > 224.5.6.7.globe: UDP, length 288
15:43:57.368869 IP (tos 0x0, ttl 255, id 6526, offset 0, flags [DF], proto UDP (17), length 7996)
    192.168.42.44.62111 > 224.5.6.7.globe: UDP, length 7968
15:43:57.368878 IP (tos 0x0, ttl 255, id 6526, offset 0, flags [DF], proto UDP (17), length 316)
    192.168.42.44.62111 > 224.5.6.7.globe: UDP, length 288
15:43:57.369264 IP (tos 0x0, ttl 255, id 6526, offset 0, flags [DF], proto UDP (17), length 7996)
    192.168.42.44.62111 > 224.5.6.7.globe: UDP, length 7968
5 packets captured
46 packets received by filter
9 packets dropped by kernel
代码副本

#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <time.h>
#include <string.h>
#include <stdio.h>

#include <iostream>
#include <string>

using namespace std;

#define HELLO_PORT 2002
#define HELLO_GROUP "224.5.6.7"
#define MSGBUFSIZE 10000

int main(int argc, char *argv[])
{
    string source_iface("192.168.42.100");
    string group(HELLO_GROUP);
    int port(HELLO_PORT);

    cout << "group: " << group << " port: " << port << " source_iface: " << source_iface << endl;

    int fd;
    if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
    {
        perror("socket");
        exit(1);
    }

    u_int yes = 1;
    if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0)
    {
        perror("Reusing ADDR failed");
        exit(1);
    }

    struct sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));

    addr.sin_family = AF_INET;

    addr.sin_port = htons(port);
    addr.sin_addr.s_addr =  (group.empty() ?
                            htonl(INADDR_ANY) :
                            inet_addr(group.c_str()));

    if (bind(fd,(struct sockaddr *)&addr, sizeof(addr)) < 0)
    {
        perror("bind");
        exit(1);
    }

    struct ip_mreq mreq;
    mreq.imr_multiaddr.s_addr = inet_addr(group.c_str());
    mreq.imr_interface.s_addr = (source_iface.empty() ? htonl(INADDR_ANY) : inet_addr(source_iface.c_str()));

    if (setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
    {
        perror("setsockopt");
        exit(1);
    }

    socklen_t addrlen;
    int nbytes;
    char msgbuf[MSGBUFSIZE];

    while (1)
    {
        memset(&msgbuf, 0, MSGBUFSIZE);

        addrlen = sizeof(addr);
        if ((nbytes = recvfrom(fd, msgbuf, MSGBUFSIZE, 0, (struct sockaddr *)&addr, &addrlen)) < 0)
        {
            perror("recvfrom");
            exit(1);
        }
        cout.write(msgbuf, nbytes);
        cout.flush();
    }

    return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
使用名称空间std;
#定义HELLO_端口2002
#定义HELLO_组“224.5.6.7”
#定义MSGBUFSIZE 10000
int main(int argc,char*argv[])
{
字符串源代码(“192.168.42.100”);
字符串组(HELLO_组);
int端口(HELLO_端口);

cout这是RHEL 7中firewalld的一个问题。创建此处描述的规则解决了一个接口的问题,但不是两个都解决了。如果我不解决它,将为此重新发布另一个问题

编辑: 使两个接口同时运行的罪魁祸首是为所有接口将rp_filter值设置为2。如果“all”类别仍然为1,则仅将其设置为1不会起任何作用

    net.ipv4.conf.all.rp_filter=2

这可以通过在/etc/sysctl.d/multicast.conf创建一个文件或使用“sysctl-w”来实现调用。

netstat-an
netstat-ng
显示了什么?ng显示我的接口正确地加入了多播组。我无法解释-an输出,但我找不到任何东西,例如,如果需要的话,看起来像我的程序的路径。我无法给你打印输出,因为我无法在访问之前到达计算机周一回去工作。
netstat-an
的输出应该告诉你连接到的IP/端口。应该有一个IP 224.5.6.7 port 2002的udp条目。我有一行说:“udp 0 0 224.5.6.7:2002 0.0.0.0:*”,但另一行说已建立,我没有注意:我可以使用两个mcsender从系统接收数据(在这里找到:)和我自己的代码,我只是将数据发送到启用环回的多播IP。但是,外部的数据不显示。注意:在标准windows 8.1机器上很容易接收,但是套接字接口非常不同,可能设置也不一样。