Форум программистов, компьютерный форум, киберфорум
Boost C++
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.56/18: Рейтинг темы: голосов - 18, средняя оценка - 4.56
4 / 4 / 0
Регистрация: 13.10.2013
Сообщений: 180
1

Как получить порт, который открывается при отправке multicast

09.05.2023, 12:52. Показов 3229. Ответов 8
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Всем доброго дня.
Проблема в следующем.
Я пытаюсь написать простую программу с использованием boost::asio, которая отправяет мультикаст запрос по протоколу UDP на адрес 239.255.255.250 по порту 1900 и должна получить ответ от всех устройств, которые откликнуться на этот запрос.

Судя по wireshark запросы отправляются и приходит ответ, НО я не могу понять где взять номер порта моего приложения, который оно открывает. То есть я не знаю, какой порт слушать в той части программы, которая обрабатывает ответ.

Вопрос - как получить номер порта, который открывает программа?

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
const short multicast_port = 1900;
 
class SenderClass
{
public:
  SenderClass(io_context& io_service,
      const address& multicast_address = address::from_string("239.255.255.250"))
    : endpoint_(multicast_address, multicast_port),
      socket_(io_service, endpoint_.protocol()),
      timer_(io_service),
      message_count_(0)
  {
    std::ostringstream os;
    
 
    
    while(true) {
        socket_.async_send_to(
            boost::asio::buffer(message_), endpoint_,
            boost::bind(&SenderClass::handle_send_to, this,
              boost::asio::placeholders::error));
        cout << "Отправлено" << endl;
        /* Ожидание следующей рассылки */
        io_context cont;
        steady_timer t(cont, asio::chrono::seconds(5));
        t.wait();
    }
  }
 
  void handle_send_to(const system::error_code& error)
  {
    if (!error)
    {
      timer_.expires_from_now(boost::posix_time::seconds(1));
      timer_.async_wait(
          boost::bind(&SenderClass::handle_timeout, this,
            boost::asio::placeholders::error));
    }
  }
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
09.05.2023, 12:52
Ответы с готовыми решениями:

При отправке UDP multicast не получаю ответов
Реализую WS-Discovery на Golang. Отправляю Probe мультикастом. Временами перестает работать....

Как получить конечный урл, который открывается по заданному
Есть урлы вида https://vm.tiktok.com/ZMLFxnnJY/ Как сделать чтобы скрипт возвращал то что он...

Зависание программы при отправке в com порт
Всем доброго времени суток! Я совсем уж новичок в программировании на c# (до этого писал на...

Как получить путь к файлу, который открывается через контекстное меню
Как получить путь к файлу, который открывается через контексное меню?

Подвисает порт RS232 при отправке данных из кода
При отправке в COM через Hercules устройство отвечает нормально, но при отправки через мое...

8
6105 / 3460 / 1406
Регистрация: 07.02.2019
Сообщений: 8,799
09.05.2023, 15:07 2
Цитата Сообщение от Kapitan79 Посмотреть сообщение
и приходит ответ
А где вы его принимаете? Не вижу в вашем коде.
async_receive_from принимает в качестве параметра endpoint, в который и сохранится адрес отправителя.
Цитата Сообщение от Kapitan79 Посмотреть сообщение
while(true)
Этого в конструкторе быть не должно, если вам нужно делать рассылку по таймеру, то и делать это нужно в его обработчике.
0
4 / 4 / 0
Регистрация: 13.10.2013
Сообщений: 180
09.05.2023, 17:08  [ТС] 3
Я уже мучаюсь несколько дней)
Был вариант с async_receive_from (приведён ниже), но по какойто причине он не работает. Запрос отправляется, порт для получения верный, но ответа я не вижу. Более того я не попадаю в метод handle_send_to, хотя, если я правильно понял, он должен запуститься. Мне не совсем понятно, зачем нужен указатель this в

C++
1
2
3
 boost::bind(&Sender::handle_send_to, this,
                    boost::asio::placeholders::error,
                    boost::asio::placeholders::bytes_transferred));
Если я правильно понял доки, здесь должна быть в качестве параметров функция и её параметры (могу ошибаться, так как вперые с этим разбираюсь). В итоге handle_send_to не выполняется и логика, приводящая к ожиданию ответа, не запускается (если я правильно понял происходящее).

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
class Sender
{
public:
    Sender(boost::asio::io_context& io_context, short port)
        : socket_(io_context, udp::endpoint(ip::address::from_string("192.168.3.2"), 59666))
    {
       socket_.set_option(ip::udp::socket::reuse_address(true));
 
       ip::address_v4  multicastAddress = ip::address_v4::from_string("239.255.255.250");
 
       ip::udp::endpoint sender_endpoint_(ip::address::from_string("239.255.255.250"), port);
 
       socket_.set_option(ip::multicast::join_group(multicastAddress));
 
 //       while (true) {
            socket_.async_send_to(
                boost::asio::buffer(data.c_str(), data.length()), sender_endpoint_,
                boost::bind(&Sender::handle_send_to, this,
                    boost::asio::placeholders::error,
                    boost::asio::placeholders::bytes_transferred));
 
            cout << "Отправлено" << endl;
 
            /* Ожидание следующей рассылки */
            boost::asio::steady_timer t(io_context, boost::asio::chrono::seconds(5));
            t.wait();
//        ////
//        }
 
 
    }
 
    void handle_receive_from(const boost::system::error_code& error,
        size_t bytes_recvd)
    {
        cout << "Есть ответ" << endl;
 
        if (!error && bytes_recvd > 0)
        {
            socket_.async_send_to(
                boost::asio::buffer(data_, bytes_recvd), sender_endpoint_,
                boost::bind(&Sender::handle_send_to, this,
                    boost::asio::placeholders::error,
                    boost::asio::placeholders::bytes_transferred));
        }
        else
        {
            socket_.async_receive_from(
                boost::asio::buffer(data_, max_length), sender_endpoint_,
                boost::bind(&Sender::handle_receive_from, this,
                    boost::asio::placeholders::error,
                    boost::asio::placeholders::bytes_transferred));
        }
    }
 
    void handle_send_to(const boost::system::error_code& /*error*/,
        size_t /*bytes_sent*/)
    {
        cout << "Отправка в процессе" << endl;
        socket_.async_receive_from(
            boost::asio::buffer(data_, max_length), sender_endpoint_,
            boost::bind(&Sender::handle_receive_from, this,
                boost::asio::placeholders::error,
                boost::asio::placeholders::bytes_transferred));
    }
 
private:
    udp::socket socket_;
    udp::endpoint sender_endpoint_;
    enum { max_length = 1024 };
    char data_[max_length];
 
    string data = "M-SEARCH * HTTP/1.1\r\n"
        "Host: 255.255.255.255:1900\r\n"
        "ST: upnp:rootdevice\r\n"
        "Man: \"ssdp:discover\"\r\n"
        "MX: 3\r\n"
        "\r\n";
};
0
6105 / 3460 / 1406
Регистрация: 07.02.2019
Сообщений: 8,799
09.05.2023, 17:20 4
Цитата Сообщение от Kapitan79 Посмотреть сообщение
Был вариант с async_receive_from (приведён ниже), но по какойто причине он не работает.
Это код, выдранный без понимания из примера udp чата в документации...
Цитата Сообщение от Kapitan79 Посмотреть сообщение
multicastAddress
Что это?
Цитата Сообщение от Kapitan79 Посмотреть сообщение
ip::udp::endpoint sender_endpoint_(ip::address::from_string("239.255.255.250"), port);
Это локальный объект, который имеет то же имя, что член класса sender_endpoint_.
Что он тут делает?
0
4 / 4 / 0
Регистрация: 13.10.2013
Сообщений: 180
09.05.2023, 17:29  [ТС] 5
Увы, понимания пока мало, это правда.
Суть задачи - отправить мультикаст запрос и получить ответ от роутера для обработки.

По поводу multicastAddress - это действительно лишняя строка. Осталась от попыток осознать как всё должно работать.

По поводу ip::udp::endpoint sender_endpoint_(ip::address::from_string("239.255 .255.250"), port):
если я правильно понял, это параметры хоста, на который отправляется пакет. В моём случае это мультикаст рассылка.
0
6105 / 3460 / 1406
Регистрация: 07.02.2019
Сообщений: 8,799
09.05.2023, 17:34 6
Цитата Сообщение от Kapitan79 Посмотреть сообщение
По поводу ip::udp::endpoint sender_endpoint_(ip::address::from_string("239.255 .255.250"), port):
если я правильно понял, это параметры хоста, на который отправляется пакет.
У вас асинхронная отправка, эта переменная умрет после завершения конструктора - в итоге UB.
0
4 / 4 / 0
Регистрация: 13.10.2013
Сообщений: 180
09.05.2023, 17:51  [ТС] 7
Спасибо!) Исправил указанные ошибки, теперь код выглядит как указано ниже. Но проблема с получением ответа всё равно осталась.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
using namespace std;
using namespace boost;
using namespace asio;
using namespace ip;
 
class Sender
{
public:
    Sender(boost::asio::io_context& io_context, short port)
        : socket_(io_context, udp::endpoint(ip::address::from_string("192.168.3.2"), 59666))
    {
        socket_.set_option(ip::udp::socket::reuse_address(true));
 
        sender_endpoint_.address(ip::address::from_string("239.255.255.250"));
        sender_endpoint_.port(port);
 
        socket_.async_send_to(
                    boost::asio::buffer(data.c_str(), data.length()), sender_endpoint_,
                    boost::bind(&Sender::handle_send_to, this,
                                boost::asio::placeholders::error,
                                boost::asio::placeholders::bytes_transferred));
 
        cout << "Отправлено" << endl;
 
        /* Ожидание следующей рассылки */
        boost::asio::steady_timer t(io_context, boost::asio::chrono::seconds(5));
        t.wait();
    }
 
    void handle_receive_from(const boost::system::error_code& error,
                             size_t bytes_recvd)
    {
        cout << "Есть ответ" << endl;
 
        if (!error && bytes_recvd > 0)
        {
            socket_.async_send_to(
                        boost::asio::buffer(data_, bytes_recvd), sender_endpoint_,
                        boost::bind(&Sender::handle_send_to, this,
                                    boost::asio::placeholders::error,
                                    boost::asio::placeholders::bytes_transferred));
        }
        else
        {
            socket_.async_receive_from(
                        boost::asio::buffer(data_, max_length), sender_endpoint_,
                        boost::bind(&Sender::handle_receive_from, this,
                                    boost::asio::placeholders::error,
                                    boost::asio::placeholders::bytes_transferred));
        }
    }
 
    void handle_send_to(const boost::system::error_code& error,
                        size_t bytes_sent)
    {
        cout << "Отправка в процессе" << endl;
        socket_.async_receive_from(
                    boost::asio::buffer(data_, max_length), sender_endpoint_,
                    boost::bind(&Sender::handle_receive_from, this,
                                boost::asio::placeholders::error,
                                boost::asio::placeholders::bytes_transferred));
    }
 
private:
    udp::socket socket_;
    udp::endpoint sender_endpoint_;
    enum { max_length = 1024 };
    char data_[max_length];
 
    string data = "M-SEARCH * HTTP/1.1\r\n"
                  "Host: 255.255.255.255:1900\r\n"
                  "ST: upnp:rootdevice\r\n"
                  "Man: \"ssdp:discover\"\r\n"
                  "MX: 3\r\n"
                  "\r\n";
};
0
6105 / 3460 / 1406
Регистрация: 07.02.2019
Сообщений: 8,799
09.05.2023, 18:19 8
Лучший ответ Сообщение было отмечено Kapitan79 как решение

Решение

Цитата Сообщение от Kapitan79 Посмотреть сообщение
Но проблема с получением ответа всё равно осталась.
Я не знаю, что вы там конкретно делаете, но если отправителя присоеденить к группе рассылки, то сам себе он отправляет.
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#include <iostream>
#include <boost/asio.hpp>
#include <boost/bind/bind.hpp>
 
using namespace std;
using namespace boost;
using namespace asio;
using namespace ip;
 
class Sender
{
public:
    Sender(boost::asio::io_context& io_context, unsigned short port)
        : socket_(io_context, udp::endpoint({}, 59666))
    {
        socket_.set_option(ip::udp::socket::reuse_address(true));
        auto multicast_address = address::from_string("239.255.255.250");
        socket_.set_option(multicast::join_group(multicast_address));
        sender_endpoint_.address(ip::address::from_string("239.255.255.250"));
        sender_endpoint_.port(port);
 
        socket_.async_send_to(
                    boost::asio::buffer(data.c_str(), data.length()), sender_endpoint_,
                    boost::bind(&Sender::handle_send_to, this,
                                boost::asio::placeholders::error,
                                boost::asio::placeholders::bytes_transferred));
 
    }
 
    void handle_receive_from(const boost::system::error_code& error,
                             size_t bytes_recvd)
    {
        
        if (!error && bytes_recvd > 0)
        {
            cout << "Есть ответ" << endl;
            socket_.async_send_to(
                        boost::asio::buffer(data_, bytes_recvd), sender_endpoint_,
                        boost::bind(&Sender::handle_send_to, this,
                                    boost::asio::placeholders::error,
                                    boost::asio::placeholders::bytes_transferred));
        }
        else
        {
            cout << "Есть ошибка" << endl;
            socket_.async_receive_from(
                        boost::asio::buffer(data_, max_length), sender_endpoint_,
                        boost::bind(&Sender::handle_receive_from, this,
                                    boost::asio::placeholders::error,
                                    boost::asio::placeholders::bytes_transferred));
        }
    }
 
    void handle_send_to(const boost::system::error_code& error,
                        size_t bytes_sent)
    {
        if (error) {
          cout << "Ошибка" << endl;
          return;
        }
        cout << "Отправлено" << endl;
        socket_.async_receive_from(
                    boost::asio::buffer(data_, max_length), sender_endpoint_,
                    boost::bind(&Sender::handle_receive_from, this,
                                boost::asio::placeholders::error,
                                boost::asio::placeholders::bytes_transferred));
    }
 
private:
    udp::socket socket_;
    udp::endpoint sender_endpoint_;
    enum { max_length = 1024 };
    char data_[max_length];
 
    string data = "M-SEARCH * HTTP/1.1\r\n"
                  "Host: 255.255.255.255:1900\r\n"
                  "ST: upnp:rootdevice\r\n"
                  "Man: \"ssdp:discover\"\r\n"
                  "MX: 3\r\n"
                  "\r\n";
};
 
int main(int argc, char *argv[])
{
  try
  {
    boost::asio::io_context context;
    Sender s(context, 59666);
    for (int i = 1; i--;)
    {
      try
      {
        context.run();
        return 0;
      }
      catch (std::exception const &e)
      {
        std::cerr << e.what() << std::endl;
      }
    }
  }
  catch (std::exception const &e)
  {
    std::cerr << e.what() << std::endl;
  }
  return 1;
}
1
4 / 4 / 0
Регистрация: 13.10.2013
Сообщений: 180
09.05.2023, 18:24  [ТС] 9
Спасибо! Большое человеческое. Буду дальше копать доку. С рабочим кодом это будет проще)
0
09.05.2023, 18:24
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
09.05.2023, 18:24
Помогаю со студенческими работами здесь

Изменение кодировки при отправке числовых сообщения на com порт
Здравствуйте! При отправке числовых сообщения на com порт выводятся непонятные символы. Пробовал...

При отправке формы открывается исходный код php
Погуглила, получается что проблема в настройках php моего сайта. Подскажите где искать эти...

Как настроить изначальный код, который открывается при создании нового проекта
Объясните пожалуйста, как в Visual C++ 2008 Express настроить изначальный шаблон кода при создании...

Получить данные как по методу UDP Multicast Streams wireshark’а через scapy или pyshark
Добрый день. Снова столкнулся с проблемой при анализе капчи. В wireshark есть меню Statistics в...

Получить $_FILES при отправке AJAX
Всем привет не знаю не ошибся ли я разделом, но попробую тут спросить, как отправить с помощью ajax...

Ошибка "процесс не может получить доступ к файлу" при отправке почты при закрытии Word
Доброго времени суток, форумчане! Возникла проблемка, написал макрос, который при закрытии...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
9
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru