读取 boost::asio UDP 广播响应

Read boost::asio UDP Broadcast Response

我正在尝试使用 boost::asio 来实现一个简单的设备发现协议。基本上我想发送一个带有 2 字节有效负载的广播消息(端口 9000)。然后读取设备的响应(假设当前存在)。在 wireshark 中,我可以看到广播已发送并且设备正在响应。但是,在我的示例代码中,我得到返回的字节数在 UDP 读取中是 0,而不是 30 字节的数据。

No.  Time      Source         Destination         Protocol  Length
1    0.00000   192.168.0.20   255.255.255.255     UDP       44        52271 -> 9000  Len = 2
2    0.00200   192.168.0.21   192.168.0.20        UDP       72        9000  -> 52271 Len = 30

我应该从不同于 broadcastEndpoint 的端点读取吗?我如何获得终点?

我是 asio 的新手,正在尝试自学,但我无法解决我做错的事情。

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

class udp_find {
public:
    udp_find(boost::asio::io_context& service, unsigned int port)
    : broadcastEndpoint_(boost::asio::ip::address_v4::broadcast(), port),
      socket_(service)
    {
        socket_.open(boost::asio::ip::udp::v4());
        socket_.set_option(boost::asio::ip::udp::socket::reuse_address(true));
        socket_.set_option(boost::asio::socket_base::broadcast(true));

        boost::array<unsigned int, 2> data = {255, 255};
        socket_.async_send_to(
                          boost::asio::buffer(data, 2), broadcastEndpoint_,
                              boost::bind(&udp_find::handle_send, this,
                                          boost::asio::placeholders::error,
                                          boost::asio::placeholders::bytes_transferred));
}

void handle_receive(const boost::system::error_code& error,
                    std::size_t bytes_transferred)
{
    std::cout << "Received Data" << bytes_transferred << std::endl;
}

void handle_send(const boost::system::error_code& error, std::size_t bytes_transferred)
{
    std::cout << "Sent Data"  << bytes_transferred << std::endl;

    socket_.async_receive_from(
                               boost::asio::buffer(buffer_), broadcastEndpoint_,
                               boost::bind(&udp_find::handle_receive, this,
                                           boost::asio::placeholders::error,
                                               boost::asio::placeholders::bytes_transferred));
    }

private:
    boost::asio::ip::udp::socket socket_;
    boost::array<char, 128> buffer_;
    boost::asio::ip::udp::endpoint broadcastEndpoint_;
};

int main()
{
    boost::asio::io_context service;
    udp_find(service, 9000);
    service.run();
}

你的第一个问题是Udefined Behaviour

您对 udp_find 类型的临时对象启动异步操作。该对象在构造后立即销毁,因此即使在您开始任何异步工作之前它也不再存在 (service.run())。

通过将 udp_find 设为局部变量而不是临时变量可以轻松解决这个问题:

udp_find op(service, 9000);

正在为我发送作品。您还需要测试接收是否有效。在我的 netstat 输出中,UDP 套接字似乎绑定到临时端口。向该端口发送数据报使我的测试成功。

您可能希望在接收之前实际 bind/connect 到广播地址(async_receive_fromendpoint& 参数是 而不是 ,我认为这是一个 output 参数)。