简体   繁体   English

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

[英]Receiving multicast data on RHEL 7 using c++

I am trying to receive multicast UDP data on a network interface on RHEL 7.2我正在尝试在 RHEL 7.2 上的网络接口上接收多播 UDP 数据

So, about my setup: NIC: Intel X540 IP: 192.168.42.100 Distro: RHEL 7.2 Multicast Address: 224.5.6.7 Port: 2002 Interface name: ens4f1所以,关于我的设置:网卡:Intel X540 IP:192.168.42.100 发行版:RHEL 7.2 多播地址:224.5.6.7 端口:2002 接口名称:ens4f1

I have 2 interfaces open, the 1 Gbit on the Mobo and one of the 10 Gbit on the intel card.我打开了 2 个接口,Mobo 上的 1 Gbit 和 intel 卡上的 10 Gbit 之一。

Like many other posts, I have data coming in and visible on both wireshark and tcpdump but my recvfrom call just hangs.像许多其他帖子一样,我在wireshark 和 tcpdump 上都有数据进入并可见,但我的 recvfrom 调用只是挂起。 My code is a copy of a similar problem described here , which appears to be working for the OP.我的代码是此处描述的类似问题的副本,它似乎适用于 OP。

Notes:笔记:

1) I run my code as root 1)我以root身份运行我的代码

2) I have tried to change the rp_filter in /proc/sys/net/ipv4/conf/ens4f1/rp_filter to 0. No change 2)我尝试将 /proc/sys/net/ipv4/conf/ens4f1/rp_filter 中的 rp_filter 更改为 0。没有变化

3) Disabling SELinux did not change anything 3) 禁用 SELinux 没有任何改变

4) Wireshark and tcpdump shows the data just fine. 4) Wireshark 和 tcpdump 显示数据很好。 Dump shown below转储如下所示

[@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

Copy of code代码副本

#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;
}

All help and suggestions are most welcome非常欢迎所有帮助和建议

Thanks谢谢

Henrik亨里克

It was an issue with the firewalld in RHEL 7. Creating a rule described here https://access.redhat.com/solutions/1587673 solved it for one interface, but not both.这是 RHEL 7 中 firewalld 的问题。创建此处描述的规则https://access.redhat.com/solutions/1587673解决了一个接口的问题,但不能同时解决这两个问题。 Will repost another question for that if I don't solve it.如果我不解决它,将重新发布另一个问题。

EDIT: The culprit for getting both running at the same time was setting the rp_filter value to 2 for all interfaces.编辑:同时运行两者的罪魁祸首是将所有接口的 rp_filter 值设置为 2。 Setting it for only 1 does not do anything if the 'all' category is still 1.如果“全部”类别仍为 1,则仅将其设置为 1 不会执行任何操作。

    net.ipv4.conf.all.rp_filter=2

This can be done by creating a file at /etc/sysctl.d/multicast.conf or using a "sysctl -w" call.这可以通过在 /etc/sysctl.d/multicast.conf 中创建一个文件或使用“sysctl -w”调用来完成。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM