简体   繁体   English

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

[英]Bind UDP socket to specific network interface using Boost.Asio

My PC has several network cards and I'm trying to receive UDP data from several broadcast devices.我的 PC 有多个网卡,我正在尝试从多个广播设备接收 UDP 数据。 Each device is isolated on a dedicated network and I'm trying to read UDP data from multiple devices at the same time.每个设备都隔离在专用网络上,我试图同时从多个设备读取 UDP 数据。 I'm using Boost version 1.67.我正在使用 Boost 版本 1.67。 Let's pretend in this post that I want to get data from one only specific device, so I want to bind on a local network interface.让我们在这篇文章中假装我想从一个特定的设备获取数据,所以我想绑定到本地网络接口。

On Windows the following code works, but on my Ubuntu 16.04 64bits machine it does not.在 Windows 上,以下代码有效,但在我的 Ubuntu 16.04 64 位机器上却无效。 Indeed, if I bind on one specific local IP address (192.168.1.1 in this example) I do not get any data.事实上,如果我绑定到一个特定的本地 IP 地址(本例中为 192.168.1.1),我不会获得任何数据。 But if I use the ANY "0.0.0.0" address then I get what I want.但是如果我使用任何“0.0.0.0”地址,那么我就会得到我想要的。 Except that in that case I don't know where it comes from.除了在那种情况下我不知道它来自哪里。 It could be received by any network card!任何网卡都可以接收!

Is it normal behavior?这是正常行为吗? Or do I need to read the sender_endpoint to know that information on Linux and filter afterwards?或者我是否需要阅读sender_endpoint才能了解有关 Linux 的信息并在之后进行过滤?

#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;
}

A little late but others might come to this as well as I have been attempting this with Boost and trying to figure out how it works.有点晚了,但其他人可能会想到这个以及我一直在尝试使用 Boost 并试图弄清楚它是如何工作的。 From reviewing this question: Fail to listen to UDP Port with boost::asio I went to this page: https://forums.codeguru.com/showthread.php?504427-boost-asio-receive-on-linux and it turns out on Linux that you need to bind to the "any address" in order to receive broadcast packets.通过审查这个问题: Fail to listen to UDP Port with boost::asio我去了这个页面: https ://forums.codeguru.com/showthread.php?504427-boost-asio-receive-on-linux 然后它变成在 Linux 上,您需要绑定到“任何地址”才能接收广播数据包。 So you would set this up as your receiving endpoint:因此,您可以将其设置为您的接收端点:

udp::endpoint(boost::asio::ip::address_v4::any(), port)

And then yes you would need to filter on the sender information.然后是的,您需要过滤发件人信息。 Seems a bit odd but seems to be the way Linux interfaces handle broadcasts.看起来有点奇怪,但似乎是 Linux 接口处理广播的方式。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM