升压:asio IPv4地址和UDP通信

解决问题 – 查看底部的解决scheme注意事项

我试图build立一个简单的应用程序来testing以太网function的微控制器。 我想要做的就是发送和接收小的UDP数据包。 代码是使用boost :: asio进行networking连接,而且非常简单。 为了debugging,我把所有的初始化从构造函数中移出来,这样我就可以检查每一步。 这是我的东西的身体:

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'd 10.1.1.7,所以目标IP应该是没有任何路由可达的。 我在32位的Win7和MSVS 10上使用BOOST 1.46.1。当我尝试127.0.0.1的IP时,它也失败了,纠正我,如果我错了,但是这应该在这种环境下工作的回环?

编辑更新:

所以感谢早先的答案,我已经得到了IP地址到我的address_v4 ,我不再试图绑定,当我打算使用连接。 代码的重大改变部分是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,以帮助减less混淆…..)

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

最终决议

我已经设法完成这项工作,所以我会发布我在一个很好的整洁列表中发现的陷阱,对于那些在类似问题上碰到这个答案的人。 我认为我遇到的主要问题是没有任何提升示例显示如何连接到指定的IP,他们都使用parsing器。 这让我很难理解这些例子。

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

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

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

  • 使用发送方法来实际传输。 不要尝试使用boost::asio::socket_base::debug(true)来启用debugging数据! 所有这个标志似乎是在其他function的发送内导致错误消息!

我还想分享一下在整个练习中我最有价值的debugging工具是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有正确的价值!