【发布时间】:2012-04-10 13:44:54
【问题描述】:
问题已解决 - 请参阅底部的解决方案说明
我正在尝试构建一个简单的应用程序来测试支持以太网的微控制器。我要做的就是发送和接收小的 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,并且当我打算使用连接时,我不再尝试绑定。显着变化的代码部分是 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 文档中做到这一点。
最终解决方案
我已经成功地完成了这项工作,所以我将把我在一个漂亮整洁的列表中找到的陷阱发布给其他任何偶然发现这个答案并遇到类似问题的人。我认为我遇到的主要问题是,没有一个 boost 示例显示如何连接到指定的 IP,它们都使用解析器。这让我更难理解这些例子。
- 使用
from_string调用转换文本IP 时,请使用下面第一个答案中的语法,而不是我上面的语法! -
在设置 UDP 套接字时,操作顺序至关重要!如果你不想在构造函数中这样做,你需要:
- 使用所需的协议打开套接字。
- 将套接字绑定到指定源 UDP 端口号的本地端点。
- 将套接字连接到指定目的地 IP 和端口号的远程端点。
在连接后尝试绑定将导致绑定失败。传输将正常运行,但您的数据包将从任意端口号发送。
- 使用发送方法来实际传输。 不要尝试使用
boost::asio::socket_base::debug(true)启用调试数据!所有这些标志似乎只是在其他功能发送中导致错误消息!
我还想分享一下,我在整个练习中最有价值的调试工具是 Wireshark。也许这只是因为我在处理这样的通信时习惯于使用 CRO 或协议分析器,但我发现能够看到在线字节显示帮助我整理了一大堆我想要的东西否则永远不会追查到。
感谢您在 IP 问题上的帮助,并帮助我了解连接和绑定之间的区别。
【问题讨论】:
-
OK,进一步更新:如果我使用
boost::asio::ip::address_v4::bytes_type代表IP,我可以成功传入我选择的任何IP。我还可以使用boost::asio::ip::address_v4::loopback()作为参数来构造端点,它的IP 值为127.0.0.1。不幸的是,当我使用这些设置中的任何一个运行时,它不会改变稍后发送的错误...... -
用这些信息编辑你的问题,它不应该是评论
标签: c++ windows network-programming boost-asio