使用 C++ 在 RHEL 7 上接收多播数据
Receiving multicast data on RHEL 7 using c++
我正尝试在 RHEL 7.2 的网络接口上接收组播 UDP 数据
所以,关于我的设置:
网卡:英特尔X540
IP:192.168.42.100
发行版:RHEL 7.2
组播地址:224.5.6.7
港口:2002
接口名称:ens4f1
我打开了2个接口,主板上的1Gbit和intel卡上的10Gbit之一。
像许多其他帖子一样,我有数据传入并且在 wireshark 和 tcpdump 上都可见,但我的 recvfrom 调用挂起。我的代码是 here 描述的类似问题的副本,它似乎适用于 OP。
备注:
1) 我 运行 我的代码是 root
2) 我尝试将 /proc/sys/net/ipv4/conf/ens4f1/rp_filter 中的 rp_filter 更改为 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;
}
欢迎所有帮助和建议
谢谢
亨里克
这是 RHEL 7 中的 firewalld 的问题。创建此处描述的规则 https://access.redhat.com/solutions/1587673 解决了一个接口的问题,但不是两个。如果我不解决它,将重新发布另一个问题。
编辑:
同时获得两个 运行 的罪魁祸首是将所有接口的 rp_filter 值设置为 2。如果 'all' 类别仍为 1,则仅将其设置为 1 不会执行任何操作。
net.ipv4.conf.all.rp_filter=2
这可以通过在 /etc/sysctl.d/multicast.conf 中创建文件或使用 "sysctl -w" 调用来完成。
我正尝试在 RHEL 7.2 的网络接口上接收组播 UDP 数据
所以,关于我的设置: 网卡:英特尔X540 IP:192.168.42.100 发行版:RHEL 7.2 组播地址:224.5.6.7 港口:2002 接口名称:ens4f1
我打开了2个接口,主板上的1Gbit和intel卡上的10Gbit之一。
像许多其他帖子一样,我有数据传入并且在 wireshark 和 tcpdump 上都可见,但我的 recvfrom 调用挂起。我的代码是 here 描述的类似问题的副本,它似乎适用于 OP。
备注:
1) 我 运行 我的代码是 root
2) 我尝试将 /proc/sys/net/ipv4/conf/ens4f1/rp_filter 中的 rp_filter 更改为 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;
}
欢迎所有帮助和建议
谢谢
亨里克
这是 RHEL 7 中的 firewalld 的问题。创建此处描述的规则 https://access.redhat.com/solutions/1587673 解决了一个接口的问题,但不是两个。如果我不解决它,将重新发布另一个问题。
编辑: 同时获得两个 运行 的罪魁祸首是将所有接口的 rp_filter 值设置为 2。如果 'all' 类别仍为 1,则仅将其设置为 1 不会执行任何操作。
net.ipv4.conf.all.rp_filter=2
这可以通过在 /etc/sysctl.d/multicast.conf 中创建文件或使用 "sysctl -w" 调用来完成。