gpt4 book ai didi

c++ - 如何使用 boost asio 接收发送到 255.255.255.255 的 UDP 广播?

转载 作者:行者123 更新时间:2023-11-27 23:49:15 24 4
gpt4 key购买 nike

我编写了一个可以在客户端或服务器模式下运行的设备发现程序。在客户端模式下,它在端口 30000 上向 255.255.255.255 发送一个 UDP 广播数据包,然后在端口 30001 上监听响应。在服务器模式下,它在端口 30000 上监听一个 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 上的类似问题,发现一些说接收套接字必须绑定(bind)到 INADDR_ANY 才能接收广播数据包。我最初是这样创建套接字的 udp::socket socket(ioService, udp::endpoint(udp::v4(), portNum));但现在已将其更改为使用 ip::address_v4::any()反而。这没有任何区别。

谁能告诉我需要更改什么才能按预期接收 UDP 广播数据包?

我在运行 Linux 的 iMX6 设备上运行它并使用 boost 1.58 进行编译。

最佳答案

我终于发现为什么我的代码从未看到广播数据包,即使 tcpdump 证明它们已被接收。在找到这个 StackOverflow 问题后:

Disable reverse path filtering from Linux kernel space

看来我只需要像这样在两台主机上禁用反向路径过滤:

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) 正常工作。

关于c++ - 如何使用 boost asio 接收发送到 255.255.255.255 的 UDP 广播?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47829979/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com