使用Boost.Asio将UDP套接字绑定到特定的网络接口

5

我的电脑有几个网络卡,我试图从多个广播设备接收UDP数据。每个设备都在专用网络上隔离开来,我正在尝试同时从多个设备读取UDP数据。 我使用的是Boost版本1.67。在这篇文章中,假设我只想从一个特定的设备获取数据,因此我想在本地网络接口上进行绑定。

在Windows上,以下代码可以工作,但是在我的Ubuntu 16.04 64位机器上无法工作。实际上,如果我绑定到一个特定的本地IP地址(例如192.168.1.1),我就无法获取任何数据。但是,如果我使用ANY "0.0.0.0"地址,那么我就可以得到我想要的东西。除了这种情况下,我不知道它来自哪里。它可能被任何网络卡接收!

这是正常行为吗?还是我需要在Linux上读取sender_endpoint以获取该信息,然后进行过滤?

#include <iostream>
#include <boost/array.hpp>
#include <boost/asio.hpp>

using boost::asio::ip::udp;

int main(int argc, char* argv[])
{
  try
  {
    boost::asio::io_context io_context;

    // Setup UDP Socket
    udp::socket socket(io_context);
    socket.open(udp::v4());

    // Bind to specific network card and chosen port
    socket.bind(udp::endpoint(boost::asio::ip::address::from_string("192.168.1.1"), 2368));

    // Prepare to receive data
    boost::array<char, 128> recv_buf;
    udp::endpoint sender_endpoint;
    size_t len = socket.receive_from(boost::asio::buffer(recv_buf), sender_endpoint);

    // Write data to std output
    std::cout.write(recv_buf.data(), len);
  }
  catch (std::exception& e)
  {
    std::cerr << e.what() << std::endl;
  }

  return 0;
}

我接下来会尝试使用Wireshark或类似的工具来嗅探网络流量。 - πάντα ῥεῖ
你检查过Ubuntu下该网卡是否与Windows下具有相同的静态IP地址吗?你也可以尝试使用一个非常高的端口号,例如56789,我记得一些Linux需要su权限才能使用低于1024的端口...我不记得了。 - nada
@πάνταῥεῖ 已完成。我有一个PCAP记录,它只显示广播正常流量。 @nada 我想你所指的数字是1024。IP地址是相同的,全局设置也是相同的。如果我绑定到任何接口,我可以在端口2368上读取数据,所以不确定你的观点在我的情况下是否有意义。 - poukill
1个回答

2
有点晚了,但其他人可能也会遇到这个问题,我一直在尝试使用Boost并试图弄清楚它的工作原理。 从检查这个问题:Fail to listen to UDP Port with boost::asio 我去了这个页面:https://forums.codeguru.com/showthread.php?504427-boost-asio-receive-on-linux 在Linux上,你需要绑定到“任何地址”才能接收广播数据包。 所以你会将这个设置为你的接收端点:
udp::endpoint(boost::asio::ip::address_v4::any(), port)

然后,您需要过滤发件人信息。这似乎有点奇怪,但似乎是Linux接口处理广播的方式。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接