boost:asio IPv4地址和UDP通信

boost:asio IPv4 address and UDP comms

本文关键字:UDP 通信 地址 IPv4 asio boost      更新时间:2023-10-16

问题已解决-请参阅底部的解决方案说明

我正在尝试构建一个简单的应用程序来测试具有以太网功能的微控制器。我只想发送和接收小UDP数据包。该代码使用boost::asio进行联网,并且非常简单。为了调试,我将所有初始化从构造函数中移出,这样我就可以检查每个步骤。这是我的东西的主体:

    boost::system::error_code myError;
    boost::asio::ip::address_v4 targetIP;
    targetIP.from_string("10.1.1.75", myError);                 // Configure output IP address. HACKHACK--Hardcoded for Debugging
    std::cout << "GetIP - " << myError.message() << std::endl;
    std::cout << "IP: " << targetIP << std::endl;
    boost::asio::ip::udp::endpoint myEndpoint;                  // Create endpoint on specified IP.
    myEndpoint.address(targetIP);
    myEndpoint.port(0x1000);
    std::cout << "Endpoint IP:   " << myEndpoint.address().to_string() << std::endl;
    std::cout << "Endpoint Port: " << myEndpoint.port() << std::endl;
    boost::asio::io_service io_service;                         // Create socket and IO service, bind socket to endpoint.
    udp::socket socket(io_service);
    socket.open( myEndpoint.protocol(), myError );
    std::cout << "Open - " << myError.message() << std::endl;
    socket.bind( myEndpoint, myError );
    std::cout << "Bind - " << myError.message() << std::endl;
    char myMessage[] = "UDP Hello World!";                      // Send basig string, enable socket level debugging.
    socket.send(boost::asio::buffer(myMessage, sizeof(myMessage)), boost::asio::socket_base::debug(true), myError);
    std::cout << "Send - " << myError.message() << std::endl;
    boost::array<char, 128> recv_buf;                           // Receive something (hopefully an echo from the uP)
    udp::endpoint sender_endpoint;
    size_t len = socket.receive_from( boost::asio::buffer(recv_buf), myEndpoint );
    std::cout.write(recv_buf.data(), len);

障碍一开始就发生了。address_v4不想接受我传递给它的IP。这个应用程序的输出是:

GetIP - The operation completed successfully
IP: 0.0.0.0
Endpoint IP:   0.0.0.0
Endpoint Port: 4096
Open - The operation completed successfully
Bind - The operation completed successfully
Send - A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied

我假设发送错误是address_v4没有正确设置的结果,但我没有理由想到会发生这样的事情。

对于那些在家里玩的人来说,我的电脑有双以太网卡,其中一个是DHCP的10.1.1.7,所以目标IP应该可以在没有任何路由的情况下访问。我在32位Win7和MSVS 10上使用BOOST 1.46.1。当我尝试127.0.0.1的IP时,它也会失败,如果我错了,请纠正我,但在这种情况下,这应该适用于环回吗?

编辑并更新:

因此,多亏了前面的答案,我已经将IP地址输入了我的address_v4,并且当我打算使用connect时,我不再尝试绑定。代码中发生重大变化的部分是TX,现在看起来像:

    socket.open( targetEndpoint.protocol(), myError );
    std::cout << "Open - " << myError.message() << std::endl;
    char myMessage[] = "UDP Hello World!";                      // Send basig string, enable socket level debugging.
    socket.send_to(boost::asio::buffer(myMessage, sizeof(myMessage)), targetEndpoint, boost::asio::socket_base::debug(true), myError);
    std::cout << "Send - " << myError.message() << std::endl;

(我将myEndpoint重命名为targetEndpoint,以帮助减少混乱……)

我现在在尝试发送时出错:
The attempted operation is not supported for the type of object referenced
在这一点上,我会给我的长子一个信息性的错误信息!无论我使用哪个目标端口,错误都是一致的。我唯一能想到的是,我需要在某个地方设置源端口,但在任何boost::asio文档中我都看不到如何做到这一点。

最终分辨率

我已经成功地完成了这项工作,所以我将把我在一个很好的列表中发现的问题发布给其他遇到类似问题的人。我认为我遇到的主要问题是,没有一个提升示例显示如何连接到指定的IP,它们都使用了解析器。这让我更难理解这些例子

  • 当使用from_string调用转换文本IP时,请使用下面第一个答案中的语法,而不是我上面的语法
  • 设置UDP套接字时,操作顺序至关重要如果你不想在构造函数中这样做,你需要:

    1. 使用所需的协议打开套接字
    2. 将套接字绑定到指定UDP端口号的本地端点
    3. 将套接字连接到指定目标IP和端口号的远程端点

    在连接之后尝试绑定将导致绑定失败。传输操作正常,但数据包将从任意端口号发送。

  • 使用发送方法进行实际传输不要尝试使用boost::asio::socket_base::debug(true)启用调试数据所有这些标志似乎都是在其他功能的发送中导致错误消息

我还想分享一下,在整个练习中,我最有价值的调试工具是Wireshark。也许这只是因为当我处理这样的通信时,我习惯了使用CRO或协议分析器,但我发现能够在有线显示器上看到字节可以帮助我整理出一整桶我永远无法追踪到的东西。

感谢您在IP问题上的帮助,并帮助我认识到连接和绑定之间的区别。

您当前看到的问题似乎是您使用了以下行:

targetIP.from_string("10.1.1.75", myError); 

boost::asio::ip::address::from_string是一个静态函数,它返回一个构造的ip::address对象。把它改成这样:

targetIP = boost::asio::ip::address::from_string("10.1.1.75", myError); 

并且您的IP地址应该正确填充。

在我的脑海中,您试图将套接字绑定到地址为10.1.1.75的端点,但这似乎是一个远程端点?我假设您希望在本地绑定它并使用send_to,因为它是UDP

这一行有一个错误:

targetIP = boost::asio::ip::address::from_string("10.1.1.75", myError);

你应该放:

targetIP = boost::asio::ip::address_v4::from_string("10.1.1.75", myError);

然后targetIP具有正确的值!