Problem resolved - see the bottom of the solution notes
I am trying to create a simple application for testing a microcontroller that supports ethernet. All I want to do is send and receive small UDP packets. The code uses boost :: asio for networks, and it's incredibly simple. For debugging, I moved the whole construct from the constructors to check every step. Here is the body of my things:
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);
Capture occurs at the very beginning. V4_address does not want to accept the IP address that I am passing to it. The result of this application 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
I assume that the send error is the result of the wrong set of address_v4 , but there is no reason why I can think of such a thing that should happen.
For those who play at home, my computer has two ethernet cards, one of which was DHCP'd 10.1.1.7, so the destination IP should be accessible without any routing. I use BOOST 1.46.1 on 32-bit Win7 and MSVS 10. It also fails when I try to execute the IP address 127.0.0.1 , correct me if I am wrong, but should this work for loopback in this context?
Edit with updates:
So, thanks to earlier answers, I got the IP address in my address_v4 , and I'm no longer trying to bind when I wanted to use connect. The significantly modified section of code is TX, which now looks like this:
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;
(I renamed myEndpoint to targetEndpoint to help reduce confusion .....)
Now I get an error when trying to send:
The attempted operation is not supported for the type of object referenced
At this point, I would give the first-born a message for an informative error message! The error is consistent no matter which destination port I use. The only thing I can think of is that I need to set the source port somewhere, but I donβt see how you can do this in any boost::asio documentation.
Final resolution
I managed to get this to work, so I'm going to post gotchas, which I found on a good neat list for anyone who comes across this answer with similar problems for me. I think that the main problem I was experiencing was that not one of the examples of enhancement ever shows how to connect to the specified IP, they all use a converter. This made the examples a lot harder to understand for me.
- When using the
from_string call to convert text IP, use the syntax from the first answer below, not my syntax above! When configuring a UDP socket, the order of operations is critical! If you do not want to do this in the constructor, you need to:
- Open the socket using the required protocol.
- Bind a socket to a local endpoint that indicates the source UDP port number.
- Connect the socket to the remote endpoint, which indicates the destination IP address and port number.
Attempting to bind after connecting will cause the binding to fail. Transmission will work very well, but your packets will be sent from an arbitrary port number.
- Use the send method for the actual transfer. Do not try to enable debugging data with
boost::asio::socket_base::debug(true) ! . All of these flags seem to trigger error messages in a functionally functional message!
I would also like to share the fact that my most valuable debugging tool in all of this exercise was Wireshark. Perhaps this is only due to the fact that I'm used to having a CRO or Analyzer Analyzer when I work in comets like this, but I found that I see that displaying bytes on the wiring helped me figure out the whole buckets that I otherwise the case would never have been discovered.
Welcomes your IP help and helps you understand the difference between connectivity and binding.