boost: asio IPv4-адрес и UDP-связь - PullRequest
8 голосов
/ 27 марта 2012

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

Я пытаюсь создать простое приложение для тестирования микроконтроллера с поддержкой Ethernet.Все, что я хочу сделать, это отправлять и получать небольшие пакеты 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 должен быть доступен без какой-либо маршрутизации.Я использую BOOST 1.46.1 на 32-битной Win7 и MSVS 10. Он также не работает, когда я пытаюсь IP-адрес 127.0.0.1, исправьте меня, если я не прав, но это должно работать для обратной связи в этом контексте?

Редактирование с обновлениями:

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

Окончательное разрешение

Мне удалось сделать эту работу, поэтому я собираюсь опубликовать ошибки, которые я нашел в хорошем аккуратном списке для всех, кто сталкивается с этим ответом и сталкивается со схожими проблемами со мной.Я думаю, что главная проблема, с которой я столкнулся, заключалась в том, что ни один из примеров наддува никогда не показывал, как подключиться к указанному IP, все они используют распознаватель.Это усложнило мне понимание примеров.

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

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

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

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

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

Приветствую вас за помощь в вопросах IP и помогаю мне понять разницу между connect и bind.

Ответы [ 3 ]

6 голосов
/ 27 марта 2012

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

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-адрес должен быть заполнен правильно.

0 голосов
/ 30 июля 2014

В этой строке есть ошибка:

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

0 голосов
/ 27 марта 2012

В верхней части моей головы вы пытаетесь привязать сокет к конечной точке с адресом 10.1.1.75, но это кажется удаленной конечной точкой? Я хотел бы предположить, что вы хотели бы связать его локально и использовать send_to, так как это UDP

...