简体   繁体   English

读取boost :: asio UDP广播响应

[英]Read boost::asio UDP Broadcast Response

I am attempting to use boost::asio to implement a simple device discovery protocol. 我正在尝试使用boost :: asio来实现简单的设备发现协议。 Basically I want to send a broadcast message (port 9000) with 2 byte payload. 基本上,我想发送带有2字节有效负载的广播消息(端口9000)。 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. 在Wireshark中,我可以看到广播已发送并且设备正在响应。 However, in my example code I get that the bytes returned is 0 in the UDP read, not 30 bytes of data. 但是,在我的示例代码中,我获得了在读取的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

Should I be reading from a different endpoint than broadcastEndpoint? 我应该从不同于broadcastEndpoint的端点读取吗? How do I get the end point? 如何获得终点?

I am new to asio and trying to teach my self, but I cannot work what I have done wrong. 我是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();
}

Your first problem is Udefined Behaviour . 您的第一个问题是Udefined Behavior

You start asynchronous operations on a temporary object of type udp_find . 您对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() ). 该对象在构造后立即被销毁,因此即使在开始任何异步工作( service.run() )之前,该对象都不存在。

That is easily fixed by making udp_find a local variable instead of a temporary: 通过将udp_find为局部变量而不是临时变量,可以轻松解决此问题:

udp_find op(service, 9000);

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. 在我的netstat输出中,似乎UDP套接字已绑定到临时端口。 Sending a datagram to that port makes the test succeed for me. 将数据报发送到该端口可以使测试成功。

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). 您可能想要在接收之前实际绑定/连接到广播地址( async_receive_fromendpoint&参数并不适用async_receive_from ,我认为这是一个输出参数)。

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

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