读取 boost::asio UDP 广播响应 [英] Read boost::asio UDP Broadcast Response

查看:38
本文介绍了读取 boost::asio UDP 广播响应的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am attempting to use boost::asio to implement a simple device discovery protocol. Basically I want to send a broadcast message (port 9000) with 2 byte payload. Then read the response from the device (assuming currently it exists). In wireshark I can see the broadcast is been sent and that the device is responding. However, in my example code I get that the bytes returned is 0 in the UDP read, not 30 bytes of data.

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 不同的端点读取数据吗?我如何获得终点?

Should I be reading from a different endpoint than broadcastEndpoint? How do I get the end point?

我是 asio 的新手并试图自学,但我无法解决我做错的事情.

I am new to asio and trying to teach my self, but I cannot work what I have done wrong.

#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()).

You start asynchronous operations on a temporary object of type udp_find. The object is destructed immediately after construction, so it doesn't exist anymore even before you start any of the async work (service.run()).

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

That is easily fixed by making udp_find a local variable instead of a temporary:

udp_find op(service, 9000);

现在发送对我有用.您还需要测试接收是否有效.在我的 netstat 输出中,UDP 套接字似乎绑定到一个临时端口.向该端口发送数据报使我的测试成功.

Now sending works for me. You will want to test that receiving works as well. In my netstat output it appears that the UDP socket is bound to an ephemeral port. Sending a datagram to that port makes the test succeed for me.

您可能想要在接收之前实际绑定/连接到广播地址(async_receive_fromendpoint& 参数不是,我认为这是一个输出参数).

You might want to actually bind/connect to the broadcast address before receiving (the endpoint& parameter to async_receive_from is not for that, I think it is an output parameter).

这篇关于读取 boost::asio UDP 广播响应的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆