尽管有 IP_MULTICAST_LOOP(Linux、C++、UDP),IP_ADD_MEMBERSHIP 结果为 "No device found"
IP_ADD_MEMBERSHIP results in "No device found" despite IP_MULTICAST_LOOP (Linux, C++, UDP)
首先,我知道这里有很多关于多播主题的问题。我还看到大多数人的问题是没有启用 IP_MULTICAST_LOOP
。我已经解决了这个问题,但仍然遇到 "No device found" 错误。
我正在编写一个程序,它可以与环回接口或连接的网络设备一起使用,具体取决于用户在硬件方面的操作(插入或拔出电缆)。我正在使用 UDP 进行数据传输。我正在使用 Linux 并使用 C++ 编写代码。
当网络电缆被插入并且说 eth0
已启动并且 运行 时,一切都很好(我的多播设置运行良好)。如果只有 lo
可用(以及 运行,根据 ifconfig
),调用
setsockopt(this->socket(), IPPROTO_IP, IP_ADD_MEMBERSHIP, &ipmReq, sizeof(ipmReq))
因 -1
失败,导致 errno
报告 "No device found"。
这是我的 MulticastEndpoint
class:
中的相关代码
MulticastEndpoint::MulticastEndpoint(std::string strMulticastGroup, unsigned short usPort) : m_strMulticastGroup(strMulticastGroup), m_usPort(usPort) {
this->setSocket(::socket(AF_INET, SOCK_DGRAM, 0));
memset(&m_saAddrGroup, 0, sizeof(m_saAddrGroup));
m_saAddrGroup.sin_family = AF_INET;
m_saAddrGroup.sin_addr.s_addr = inet_addr(m_strMulticastGroup.c_str());
m_saAddrGroup.sin_port = htons(m_usPort);
unsigned int unYes = 1;
bool bOK = false;
if(setsockopt(this->socket(), SOL_SOCKET, SO_REUSEADDR, &unYes, sizeof(unYes)) >= 0) {
if(setsockopt(this->socket(), IPPROTO_IP, IP_MULTICAST_LOOP, &unYes, sizeof(unYes)) >= 0) {
memset(&m_saAddrAny, 0, sizeof(m_saAddrAny));
m_saAddrAny.sin_family = AF_INET;
m_saAddrAny.sin_addr.s_addr = htonl(INADDR_ANY);
m_saAddrAny.sin_port = htons(m_usPort);
if(bind(this->socket(), (struct sockaddr*)&m_saAddrAny, sizeof(m_saAddrAny)) >= 0) {
struct ip_mreq ipmReq;
ipmReq.imr_multiaddr.s_addr = inet_addr(m_strMulticastGroup.c_str());
ipmReq.imr_interface.s_addr = htonl(INADDR_ANY);
if(setsockopt(this->socket(), IPPROTO_IP, IP_ADD_MEMBERSHIP, &ipmReq, sizeof(ipmReq)) >= 0) {
bOK = true;
}
}
}
}
if(!bOK) {
std::cerr << strerror(errno) << std::endl;
::close(this->socket());
this->setSocket(-1);
}
std::cout << this->socket() << std::endl;
}
class 是用多播地址 224.0.0.1
和端口 2077
实例化的。 setSocket(int)
和 socket()
方法是一个简单的 setter 和 getter 函数,将套接字存储为实例中的 int
。
有人知道这件事吗?从理论上讲,多播应该只在 lo
上工作,不是吗?另外,也许我用错了通用多播地址?就我对 linux 套接字的理解而言,INADDR_ANY
也应该涵盖环回接口。如果在这种情况下有误,请纠正我。
非常感谢任何启发。
环回接口通常不支持多播。
如果你 运行 ifconfig -a
当你有 eth0
up 和 运行ning 时,你会看到 eth0
有一个标志 MULTICAST
,而 lo
没有。
这是我的一台机器显示的内容:
eth0 Link encap:Ethernet HWaddr 00:11:22:33:44:55
inet addr:10.112.161.84 Bcast:10.112.161.127 Mask:255.255.255.192
inet6 addr: fe80::211:22ff:fe33:4455/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:20001770 errors:0 dropped:0 overruns:0 frame:0
TX packets:10074436 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:4589702477 (4.2 GiB) TX bytes:2896096295 (2.6 GiB)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:16436 Metric:1
RX packets:1212663 errors:0 dropped:0 overruns:0 frame:0
TX packets:1212663 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:60939041 (58.1 MiB) TX bytes:60939041 (58.1 MiB)
编辑:
为了使其正常工作,您需要在环回上手动打开多播:
sudo ifconfig lo multicast
完成后,您应该能够在环回时加入多播组,但是您需要为 ipmReq.imr_interface
指定 127.0.0.1 而不是 INADDR_ANY
。
首先,我知道这里有很多关于多播主题的问题。我还看到大多数人的问题是没有启用 IP_MULTICAST_LOOP
。我已经解决了这个问题,但仍然遇到 "No device found" 错误。
我正在编写一个程序,它可以与环回接口或连接的网络设备一起使用,具体取决于用户在硬件方面的操作(插入或拔出电缆)。我正在使用 UDP 进行数据传输。我正在使用 Linux 并使用 C++ 编写代码。
当网络电缆被插入并且说 eth0
已启动并且 运行 时,一切都很好(我的多播设置运行良好)。如果只有 lo
可用(以及 运行,根据 ifconfig
),调用
setsockopt(this->socket(), IPPROTO_IP, IP_ADD_MEMBERSHIP, &ipmReq, sizeof(ipmReq))
因 -1
失败,导致 errno
报告 "No device found"。
这是我的 MulticastEndpoint
class:
MulticastEndpoint::MulticastEndpoint(std::string strMulticastGroup, unsigned short usPort) : m_strMulticastGroup(strMulticastGroup), m_usPort(usPort) {
this->setSocket(::socket(AF_INET, SOCK_DGRAM, 0));
memset(&m_saAddrGroup, 0, sizeof(m_saAddrGroup));
m_saAddrGroup.sin_family = AF_INET;
m_saAddrGroup.sin_addr.s_addr = inet_addr(m_strMulticastGroup.c_str());
m_saAddrGroup.sin_port = htons(m_usPort);
unsigned int unYes = 1;
bool bOK = false;
if(setsockopt(this->socket(), SOL_SOCKET, SO_REUSEADDR, &unYes, sizeof(unYes)) >= 0) {
if(setsockopt(this->socket(), IPPROTO_IP, IP_MULTICAST_LOOP, &unYes, sizeof(unYes)) >= 0) {
memset(&m_saAddrAny, 0, sizeof(m_saAddrAny));
m_saAddrAny.sin_family = AF_INET;
m_saAddrAny.sin_addr.s_addr = htonl(INADDR_ANY);
m_saAddrAny.sin_port = htons(m_usPort);
if(bind(this->socket(), (struct sockaddr*)&m_saAddrAny, sizeof(m_saAddrAny)) >= 0) {
struct ip_mreq ipmReq;
ipmReq.imr_multiaddr.s_addr = inet_addr(m_strMulticastGroup.c_str());
ipmReq.imr_interface.s_addr = htonl(INADDR_ANY);
if(setsockopt(this->socket(), IPPROTO_IP, IP_ADD_MEMBERSHIP, &ipmReq, sizeof(ipmReq)) >= 0) {
bOK = true;
}
}
}
}
if(!bOK) {
std::cerr << strerror(errno) << std::endl;
::close(this->socket());
this->setSocket(-1);
}
std::cout << this->socket() << std::endl;
}
class 是用多播地址 224.0.0.1
和端口 2077
实例化的。 setSocket(int)
和 socket()
方法是一个简单的 setter 和 getter 函数,将套接字存储为实例中的 int
。
有人知道这件事吗?从理论上讲,多播应该只在 lo
上工作,不是吗?另外,也许我用错了通用多播地址?就我对 linux 套接字的理解而言,INADDR_ANY
也应该涵盖环回接口。如果在这种情况下有误,请纠正我。
非常感谢任何启发。
环回接口通常不支持多播。
如果你 运行 ifconfig -a
当你有 eth0
up 和 运行ning 时,你会看到 eth0
有一个标志 MULTICAST
,而 lo
没有。
这是我的一台机器显示的内容:
eth0 Link encap:Ethernet HWaddr 00:11:22:33:44:55
inet addr:10.112.161.84 Bcast:10.112.161.127 Mask:255.255.255.192
inet6 addr: fe80::211:22ff:fe33:4455/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:20001770 errors:0 dropped:0 overruns:0 frame:0
TX packets:10074436 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:4589702477 (4.2 GiB) TX bytes:2896096295 (2.6 GiB)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:16436 Metric:1
RX packets:1212663 errors:0 dropped:0 overruns:0 frame:0
TX packets:1212663 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:60939041 (58.1 MiB) TX bytes:60939041 (58.1 MiB)
编辑:
为了使其正常工作,您需要在环回上手动打开多播:
sudo ifconfig lo multicast
完成后,您应该能够在环回时加入多播组,但是您需要为 ipmReq.imr_interface
指定 127.0.0.1 而不是 INADDR_ANY
。