boost: asio IPv4-адрес и UDP-связь

проблема решена - см. внизу примечания к решению

Я пытаюсь создать простое приложение для тестирования микроконтроллера с поддержкой ethernet. Все, что я хочу сделать, это отправлять и получать небольшие UDP-пакеты. Код использует boost:: asio для сети и невероятно прост. Для отладки я переместил всю инициализацию из конструкторов, чтобы я мог проверить каждый шаг. Вот тело моих вещей:--13-->

    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 неправильно устанавливается, но нет причин, по которым я могу думать о том, что такое происходит.

для тех, кто играет дома, Мой компьютер имеет две карты ethernet, одна из которых была DHCP 10.1.1.7, поэтому целевой IP должен быть доступен без какой-либо маршрутизации. Я использую BOOST 1.46.1 на 32-разрядных Win7 и MSVS 10. Он также терпит неудачу, когда я пытаюсь IP 127.0.0.1, поправьте меня, если я ошибаюсь, но это должно работать для loopback в этом контексте?

изменить с обновлениями:

так что благодаря более ранним ответам я получил 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 документация.

финал Разрешение

мне удалось сделать эту работу, поэтому я собираюсь опубликовать gotchas, которые я нашел в хорошем аккуратном списке для всех, кто натыкается на этот ответ с аналогичными проблемами для меня. Я думаю, что основная проблема у меня была в том, что ни один из примеров boost никогда не показывает, как подключиться к указанному IP, все они используют решатель. Из-за этого мне было гораздо труднее понять примеры.

  • при использовании from_string вызов для преобразования текстового IP-адреса используйте синтаксис из первого ответа ниже, а не мой синтаксис выше!
  • при настройке сокета UDP,порядок операций имеет решающее значение! если вы не хотите делать это в конструкторе, вам нужно:

    1. откройте сокет, используя требуемый протокол.
    2. привязать сокет к локальной конечной точке, которая указывает источник номер порта UDP.
    3. подключите разъем к удаленной конечной точке, которая указывает the назначения IP и номер порта.

    попытка привязки после подключения приведет к сбою привязки. Передача будет работать нормально, но ваши пакеты будут отправлены с произвольного номера порта.

  • используйте метод send для фактической передачи. не пытайтесь включить отладку данных с помощью boost::asio::socket_base::debug(true)! все, что этот флаг, похоже, делает, это вызывает сообщения об ошибках в пределах иначе функционального отправить!

я также хотел бы поделиться тем, что моим самым ценным инструментом отладки во всем этом упражнении был Wireshark. Может быть, это только потому, что я привык иметь CRO или анализатор протоколов, когда я работаю над такими связями, но я обнаружил, что возможность видеть байты на проводном дисплее помогла мне разобраться в целом ведро вещей, которые я бы никогда не выследил.

ура за вашу помощь по вопросам IP и помогает мне понять разницу между подключение и привязка.

3 ответов


проблема, которую вы в настоящее время видите, похоже, ваше использование этой строки:

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 имеет правильное значение!