boost:asio IPv4地址和UDP通讯 [英] boost:asio IPv4 address and UDP comms

查看:106
本文介绍了boost:asio IPv4地址和UDP通讯的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

I'm trying to build a simple app to test an ethernet-capable microcontroller. All I want to do is send and receive small UDP packets. The code is using boost::asio for the networking, and is incredibly simple. For debugging I moved all the intialisation out of the constructors so I could check each step. Here's the body of my stuff:

    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.该应用程序的输出为:

The snag happens right at the beginning. The address_v4 doesn't want to accept the IP that I'm passing into it. The output of this app is:

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设置不正确的结果,但我没有理由想到发生这种情况.

I'm assuming the send error is a result of the address_v4 not getting set correctly, but there is no reason that I can think of for such a thing to be taking place.

对于那些在家中玩耍的人,我的PC配备了双以太网卡,其中之一已被DHCP认证为10.1.1.7,因此目标IP应该无需任何路由即可到达.我在32位Win7和MSVS 10上使用BOOST 1.46.1.当我尝试127.0.0.1的IP时也失败了,如果我输入错了,请更正我,但是在这种情况下应该可以环回?

For those playing along at home, my PC has dual ethernet cards, one of which has been DHCP'd 10.1.1.7, so the target IP should be reachable without any routing. I'm using BOOST 1.46.1 on 32-bit Win7 and MSVS 10. It also fails when I try an IP of 127.0.0.1, correct me if I'm wrong but that should work for loopback in this context?

使用更新进行

因此,由于先前的回答,我将IP地址添加到了address_v4中,并且在我打算使用connect时不再尝试绑定.代码的显着更改部分是TX,现在看起来像这样:

So thanks to the earlier answers I've gotten the IP address into my address_v4, and I'm no longer trying to bind when I meant to use connect. The significanly changed section of code is the TX, which now looks like:

    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以帮助减少混乱.....)

(I renamed myEndpoint to targetEndpoint to help reduce confusion.....)

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

I now get the error while trying to send:
The attempted operation is not supported for the type of object referenced
I would give my firstborn for an informative error message at this point! The error is consistent regardless of which target port I use. The only thing I can think of is that I need to be setting the source port somewhere, but I don't see how you can do that in any of the boost::asio documentation.

最终分辨率

我设法做到了这一点,所以我要把我发现的陷阱张贴在一个整洁的列表中,以供其他偶然发现此问题并遇到类似问题的人使用.我认为我遇到的主要问题是,没有一个Boost示例能够显示如何连接到指定的IP,它们都使用了解析器.这使这些例子对我来说很难理解.

I have managed to make this work, so I'm going to post the gotchas that I found in a nice neat list for anyone else who stumbles across this answer with similar problems to me. I think the main issue I had was that none of the boost examples ever show how to connect to a specified IP, they all use a resolver. It made the examples a lot harder to understand for me.

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

  • When using the from_string call to convert a text IP, use the syntax from the first answer below rather than my syntax above!
  • When setting up the UDP socket, order of operations is crucial! If you don't want to do it in the constructor you need to:

  1. 使用所需的协议打开套接字.
  2. 将套接字绑定到指定 source UDP端口号的本地端点.
  3. 将套接字连接到指定目标 IP和端口号的远程端点.
  1. Open the socket using the required protocol.
  2. Bind the socket to a local endpoint which specifies the source UDP port number.
  3. Connect the socket to the remote endpoint which specifies the destination IP and Port number.

在连接后尝试绑定将导致绑定失败.传输可以正常运行,但是您的数据包将从任意端口号发送.

Attempting to bind after the connect will cause the bind to fail. The transmission will operate just fine, but your packets will be sent from an arbitrary port number.

我还想分享一下,我在整个练习中最有价值的调试工具是Wireshark.也许仅仅是因为我在处理此类通信时习惯使用CRO或协议分析器,但是我发现能够看到线控字节显示可以帮助我整理出一大堆东西否则就永远找不到.

I'd also like to share that my most valuable debugging tool in this entire exercise was Wireshark. Maybe it's only because I'm used to having a CRO or Protocol Analyser when I'm working on comms like this, but I found being able to see the bytes-on-wire display helped me sort out a whole bucketload of stuff that I would otherwise never have tracked down.

为您在IP问题上的帮助而欢呼,并帮助我实现了连接和绑定之间的区别.

Cheers for your help on the IP issues and helping me realise the difference between connect and bind.

推荐答案

您当前看到的问题似乎是您使用此行的原因:

The problem you are currently seeing appears to be your usage of this line:

targetIP.from_string("10.1.1.75", myError); 

boost::asio::ip::address::from_string是静态函数,它返回构造的ip::address对象.对其进行更改,使其看起来像这样:

boost::asio::ip::address::from_string is a static function, that returns a constructed ip::address object. Change it to look like this:

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

您的IP地址应正确填充.

And your IP address should be populated properly.

这篇关于boost:asio IPv4地址和UDP通讯的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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