![](/img/trans.png)
[英]Computers on LAN do not consistently receive a UDP broadcast to 255.255.255.255 using boost::asio C++
[英]How to receive a UDP broadcast sent to 255.255.255.255 using boost asio?
我已经编写了可以在客户端或服务器模式下运行的设备发现程序。 在客户端模式下,它向端口30000上的255.255.255.255发送UDP广播数据包,然后在端口30001上侦听响应。在服务器模式下,它在端口30000上侦听UDP广播的UDP数据包,并在端口30001上向255.255.255.255发送UDP广播数据包作为回应。
当我在2个IP地址为192.168.10.61和192.168.10.62的设备上运行该程序时,它们都可以正常运行。 该程序的重点是允许具有未知IP地址的设备发现彼此,只要它们连接到同一物理网络即可。 因此,为了进行测试,我将第一个设备的IP地址更改为随机的内容,例如12.34.56.42/255.255.240。 现在它停止工作了。
在192.168.10.62机器上使用tcpdump,我可以看到收到了来自12.134.56.42机器的UDP数据包:
# tcpdump -i eth0 port 30000 -c 1 -v
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
17:38:02.552427 IP (tos 0x0, ttl 64, id 18835, offset 0, flags [DF], proto UDP (17), length 49)
12.34.56.42.56815 > 255.255.255.255.30000: UDP, length 21
1 packet captured
6 packets received by filter
0 packets dropped by kernel
但我的发现程序不再收到它。 这是我用来接收UDP广播数据包的代码:
int WaitForPacket(uint16_t portNum, vector<char>& udpBuf, udp::endpoint& remoteEndpoint, const chrono::milliseconds timeout)
{
io_service ioService;
udp::socket socket(ioService, udp::endpoint(boost::asio::ip::address_v4::any(), portNum));
socket.set_option(socket_base::broadcast(true));
boost::system::error_code error;
int numBytes = receive_from(socket, buffer(udpBuf), remoteEndpoint, error, timeout);
if (error && error != error::message_size && error != error::timed_out)
{
printf("Got error: %s\n", error.message().c_str());
return -1;
}
return numBytes;
}
/*
* The boost asio library does not provide a blocking read with timeout function so we have to roll our own.
*/
int receive_from(
boost::asio::ip::udp::socket& socket,
const boost::asio::mutable_buffers_1& buf,
boost::asio::ip::udp::endpoint& remoteEndpoint,
boost::system::error_code& error,
chrono::milliseconds timeout)
{
volatile bool ioDone = false;
int numBytesReceived = 0;
boost::asio::io_service& ioService = socket.get_io_service();
socket.async_receive_from(buf, remoteEndpoint,
[&error, &ioDone, &numBytesReceived](const boost::system::error_code& errorAsync, size_t bytesReceived)
{
ioDone = true;
error = errorAsync;
numBytesReceived = bytesReceived;
});
this_thread::sleep_for(chrono::milliseconds(100));
ioService.reset();
ioService.poll_one();
auto endTime = chrono::system_clock::now() + timeout;
while (!ioDone)
{
ioService.reset();
this_thread::sleep_for(chrono::milliseconds(100));
auto now = chrono::system_clock::now();
if (now > endTime)
{
socket.cancel();
error = error::timed_out;
return 0;
}
ioService.poll_one();
}
ioService.reset();
return numBytesReceived;
}
我在Stack Overflow上检查了类似的问题,发现有些问题说接收套接字必须绑定到INADDR_ANY才能接收广播数据包。 我最初创建的套接字是这样的udp::socket socket(ioService, udp::endpoint(udp::v4(), portNum));
但现在已将其更改为使用ip::address_v4::any()
代替。 没什么区别。
有人可以告诉我为了接收UDP广播数据包而需要进行哪些更改吗?
我正在运行Linux的iMX6设备上运行此程序,并使用boost 1.58进行编译。
我终于发现为什么即使tcpdump证明已接收到广播数据包,我的代码也仍然看不到广播数据包。 找到这个StackOverflow问题之后:
看来我只需要像这样在两台主机上禁用反向路径过滤:
echo 0 > /proc/sys/net/ipv4/conf/all/rp_filter
echo 0 > /proc/sys/net/ipv4/conf/eth0/rp_filter
然后我的代码无需修改即可完美运行。 希望这将帮助其他人想知道为什么他们无法使UDP广播到达网络广播地址(255.255.255.255)正常工作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.