Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 5.00/8: Рейтинг темы: голосов - 8, средняя оценка - 5.00
1 / 1 / 0
Регистрация: 04.08.2021
Сообщений: 193

Сокет для получения udp пакетов с определенным портом

08.04.2022, 12:56. Показов 1747. Ответов 13
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый день
Нужно написать сокет, который прослушивал бы определенный порт и получал пакеты, которые ему адресованы. Сообщения идут на порт 45321, на мой ip адрес. В wireshark я их вижу. Но никак не могу получить их сокетом, и не понимаю что не так.

Создание сокета, где DATA_PORT = 45321

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
SOCKET DataReader::createdSocketUnicast()
{
    SOCKET udpSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
 
    if (udpSocket == INVALID_SOCKET)
        closeSocket("Failed creating UDP DataSender socket", udpSocket);
 
    SOCKADDR_IN addr;
    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(DATA_PORT);
    addr.sin_addr.s_addr = _localIP.toIPv4Address();
 
    BOOL opt = TRUE;
    if (setsockopt(udpSocket, SOL_SOCKET, SO_REUSEADDR, (char*)&opt, sizeof(opt)) == -1)
        return closeSocket("Set opt SO_REUSEADDR  failed with error", udpSocket);
 
    if (::bind(udpSocket, (SOCKADDR*)&addr, sizeof(addr)) != NO_ERROR)  // без :: компилятор берет функцию из стандартной библиотеки, а не winsock
        return closeSocket("UDP socket receiver bind  failed with error", udpSocket);
 
    u_long iMode = 1; //при iMode = 0 блок режим
    if (ioctlsocket(udpSocket, FIONBIO, &iMode) != NO_ERROR)
        return closeSocket("Set opt ioctsocket  failed with error", udpSocket);
 
    return udpSocket;
}

И попытка приема сообщений

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
SOCKET socketUnicast = createdSocketUnicast();
    if (socketUnicast == INVALID_SOCKET)
    {
        closeSocket("Failed creating socketUnicast socket", socketUnicast);
        return;
    }
    while (isWorking)
    {
        memset(Buffer, 0, sizeof(Buffer));
 
        int countRecv = recvfrom(socketUnicast, Buffer, MAX_PACKET_SIZE, 0, (SOCKADDR*)&addrFrom, &addrFromSize);
        if (countRecv == SOCKET_ERROR)
            continue;
           ..........................................................
        }
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
08.04.2022, 12:56
Ответы с готовыми решениями:

Как только происходит попытка создать сокет для UDP - сокет TCP сразу ломается (выдает 10093).
Добрый день. Пытаюсь сделать соединение, использующее два канала обмена данными - TCP для управления в режиме клмиента, и UDP - для...

UDP сокет для прослушивания broadcast
Добрый день Нужно создать UDP сокет для прослушивания broadcast, который идет от железки. При создании сокета в sockaddr_in нужно...

Один сокет для TCP и UDP
Привет. Клиент-серверное приложение в один промежуток времени использует TCP, но через некоторое время нужно начать передавать и принимать...

13
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
08.04.2022, 13:19
Цитата Сообщение от Horwood Посмотреть сообщение
Сообщения идут на порт 45321
А где привязка к этому порту в коде, который должен получать дейтаграммы?
0
1 / 1 / 0
Регистрация: 04.08.2021
Сообщений: 193
08.04.2022, 13:41  [ТС]
Вот - addr.sin_port = htons(DATA_PORT);

Я добавляю ему порт при создании сокета
0
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
08.04.2022, 14:30
Horwood,
Да, увидел вызов bind. А есть возможность привести полный код, так что бы не было никаких скрытых данных. Например, отсюда не видно, что возвращает _localIP.toIPv4Address(); и каким образом дейтаграмма отправляется на указанный порт...

Добавлено через 4 минуты
Так же не видно вызова WSAStartup
0
 Аватар для Annemesski
2670 / 1333 / 479
Регистрация: 08.11.2016
Сообщений: 3,679
08.04.2022, 14:30
C++
12
13
//addr.sin_addr.s_addr = _localIP.toIPv4Address();
addr.sin_addr.s_addr = INADDR_ANY;
0
1 / 1 / 0
Регистрация: 04.08.2021
Сообщений: 193
08.04.2022, 14:38  [ТС]
Цитата Сообщение от Annemesski Посмотреть сообщение
C++
12
13
//addr.sin_addr.s_addr = _localIP.toIPv4Address();
addr.sin_addr.s_addr = INADDR_ANY;
Нет, это не помогло
0
 Аватар для Annemesski
2670 / 1333 / 479
Регистрация: 08.11.2016
Сообщений: 3,679
08.04.2022, 14:45
Horwood,
Цитата Сообщение от Horwood Посмотреть сообщение
C++
8
SOCKADDR_IN addr;
эту структуру храните в составе Вашего DataReader, а не создавайте на стеке, по окончании SOCKET DataReader::createdSocketUnicast() структура умирает и не доживает до вызова recvfrom
0
1 / 1 / 0
Регистрация: 04.08.2021
Сообщений: 193
08.04.2022, 14:56  [ТС]
Имеется класс корневой, в котором остальные потоки приема и передачи создаются, тут вызывается WSAStartup.

C++
1
2
3
4
5
6
7
WSADATA wsadata;
    if (WSAStartup(MAKEWORD(2, 2), &wsadata) != NO_ERROR)
        emit messageToLog("Failed WSASTARTUP while creating UDP socket", "red");
 
    dataReader = new DataReader(&_localIP);
    connect(dataReader, &DataReader::messageToLog, this, &ProxyCore::sendMessageToLog);
    dataReader->start();

На указанный порт отправляется вот таким образом, DATA_PORT тот же что и при создании сокета выше, на прием пакетов:

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
SOCKET broadcast = createdSocket();
    if (broadcast == INVALID_SOCKET)
    {
        closeSocket("Failed creating UDP socket", broadcast);
        return;
    }
 
    SOCKADDR_IN addrFrom = fillAddr(QHostAddress(), 0);                     // передаем нулевые параметры потому, что они будут заполнены сами при получении пакета
    int addrFromSize = sizeof(addrFrom);
    const SOCKADDR_IN addrSendUDP = fillAddr(_dataSender->_remoteIP, DATA_PORT);//заполняем куда полетит пакет
 
    char Buffer[MAX_PACKET_SIZE];                                           // сюда принимаем пакет
    char bufferSendUDP[MAX_PACKET_SIZE];                                    // сюда копируем пакет и отправляем
 
    while (isWorking)
    {
        memset(Buffer, 0, sizeof(Buffer));
        memset(bufferSendUDP, 0, sizeof(bufferSendUDP));
 
        int countRecv = recvfrom(broadcast, Buffer, MAX_PACKET_SIZE, 0, (SOCKADDR*)&addrFrom, &addrFromSize);
        if (countRecv == SOCKET_ERROR)
            continue;
 
        QHostAddress addBroad(addrFrom.sin_addr.s_addr);
        if ((_dataSender->_localIP.toIPv4Address() & info.mask.toIPv4Address()) != ((addBroad.toIPv4Address() & info.mask.toIPv4Address())))
            continue;
 
        // заполняем данные
        Payload* payloadHeaders = (Payload*)bufferSendUDP;
        memcpy(bufferSendUDP + sizeof(Payload), (char*)&Buffer, countRecv);
 
        // заполняем заголовки
        fillHeadersUDP(payloadHeaders);
 
        countRecv += sizeof(UDPHeader);
        //заполняем заголовок UDP
        payloadHeaders->udpHeader.dst_port = addrFrom.sin_port;  // порт получателя равен src_port из полученного сообщения  
        payloadHeaders->udpHeader.src_port = addrFrom.sin_port;  // порт отправителя равен src_port из полученного сообщения 
        payloadHeaders->udpHeader.length = _byteswap_ushort(countRecv);
        payloadHeaders->udpHeader.crc = 0;
 
        countRecv += sizeof(IPHeader);
        // заполняем заголовок IP
        payloadHeaders->ipHeader.iph_length = _byteswap_ushort(countRecv);
        payloadHeaders->ipHeader.iph_xsum = 0;
        payloadHeaders->ipHeader.iph_src = addrFrom.sin_addr.s_addr;
        countRecv += sizeof(ProxyHeader);
 
        // отправляем данные
        if (sendto(*_dataSender->data, (char*)bufferSendUDP, countRecv, 0, (SOCKADDR*)&addrSendUDP, sizeof(addrSendUDP)) == SOCKET_ERROR)
        {
            emit messageToLog("Failed to send from DiggerBroadcast", "red");
            continue;
        }
    }
Добавлено через 10 минут
Цитата Сообщение от Annemesski Посмотреть сообщение
Horwood,

эту структуру храните в составе Вашего DataReader, а не создавайте на стеке, по окончании SOCKET DataReader::createdSocketUnicast() структура умирает и не доживает до вызова recvfrom

Тоже не помогло, перенес создание сокета прям в общую функцию - все равно не видит пакетов.

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
SOCKET udpSocket = socket(AF_INET, SOCK_DGRAM, 0);
    if (udpSocket == INVALID_SOCKET)
    {
        closeSocket("Failed creating UDP socket in func", udpSocket);
        return;
    }
        
    SOCKADDR_IN addr;
    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(PORT_DATA);
    addr.sin_addr.s_addr = INADDR_ANY;
 
    BOOL opt = TRUE;
    if (setsockopt(udpSocket, SOL_SOCKET, SO_REUSEADDR, (char*)&opt, sizeof(opt)))
    {
        closeSocket("Set opt SO_REUSEADDR failed", udpSocket);
        return;
    }
        
    if (::bind(udpSocket, (SOCKADDR*)&addr, sizeof(addr)) != NO_ERROR)  // без :: компилятор берет функцию из стандартной библиотеки, а не winsock
    {
        closeSocket("UDP socket receiver bind failed", udpSocket);
        return;
    }
        
    u_long iMode = 1; //при iMode = 0 блок режим
    if (ioctlsocket(udpSocket, FIONBIO, &iMode) != NO_ERROR)
    {
        closeSocket("Set opt ioctsocket failed", udpSocket);
        return;
    }    
 
    SOCKADDR_IN addrFrom = fillAddr(QHostAddress(), 0);           // передаем нулевые параметры потому, что они будут заполнены сами при получении пакета
    int addrFromSize = sizeof(addrFrom);
 
    char Buffer[MAX_PACKET_SIZE];
 
    while (isWorking)
    {
        memset(Buffer, 0, sizeof(Buffer));
 
        int countRecv = recvfrom(udpSocket, Buffer, MAX_PACKET_SIZE, 0, (SOCKADDR*)&addrFrom, &addrFromSize);
        if (countRecv == SOCKET_ERROR)
            continue;
               ........................................................
0
 Аватар для Annemesski
2670 / 1333 / 479
Регистрация: 08.11.2016
Сообщений: 3,679
08.04.2022, 15:05
Цитата Сообщение от Horwood Посмотреть сообщение
Тоже не помогло
ну да, сокет уже связан, структура ему не нужна. Покажите что выдаст WSAGetLastError если добавить такую проверку:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
    SOCKET socketUnicast = createdSocketUnicast();
    if (socketUnicast == INVALID_SOCKET)
    {
        closeSocket("Failed creating socketUnicast socket", socketUnicast);
        return;
    }
    while (isWorking)
    {
        memset(Buffer, 0, sizeof(Buffer));
 
        int countRecv = recvfrom(socketUnicast, Buffer, MAX_PACKET_SIZE, 0, (SOCKADDR*)&addrFrom, &addrFromSize);
        if (countRecv == SOCKET_ERROR)
        {
            if (WSAGetLastError() != EWOULDBLOCK)
                std::cout << WSAGetLastError();
            continue;
           ..........................................................
        }
Ну и так (по секрету): зачем используете winsock2.h совместно с Qt - чем QUdpSocket не угодил?
0
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
08.04.2022, 15:41
Horwood,
По прежнему не видно, что возвращает toIPv4Address. Отправка/прием данных происходит на одной машине или удаленно?

Добавлено через 2 минуты
Цитата Сообщение от Annemesski Посмотреть сообщение
чем QUdpSocket не угодил?
тоже интересно
0
1 / 1 / 0
Регистрация: 04.08.2021
Сообщений: 193
08.04.2022, 17:20  [ТС]
Цитата Сообщение от Annemesski Посмотреть сообщение
ну да, сокет уже связан, структура ему не нужна. Покажите что выдаст WSAGetLastError если добавить такую проверку:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
    SOCKET socketUnicast = createdSocketUnicast();
    if (socketUnicast == INVALID_SOCKET)
    {
        closeSocket("Failed creating socketUnicast socket", socketUnicast);
        return;
    }
    while (isWorking)
    {
        memset(Buffer, 0, sizeof(Buffer));
 
        int countRecv = recvfrom(socketUnicast, Buffer, MAX_PACKET_SIZE, 0, (SOCKADDR*)&addrFrom, &addrFromSize);
        if (countRecv == SOCKET_ERROR)
        {
            if (WSAGetLastError() != EWOULDBLOCK)
                std::cout << WSAGetLastError();
            continue;
           ..........................................................
        }
Ну и так (по секрету): зачем используете winsock2.h совместно с Qt - чем QUdpSocket не угодил?

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

Добавлено через 1 час 7 минут
WSAGetLastError выдает код ошибки 10035

Добавлено через 12 минут
Цитата Сообщение от Undisputed Посмотреть сообщение
Horwood,
По прежнему не видно, что возвращает toIPv4Address. Отправка/прием данных происходит на одной машине или удаленно?

Добавлено через 2 минуты

тоже интересно
Отправка пакетов, которые мне нжно принять происходит на другой машине из другой сети.

QHostAddress используется для хранения адресов
0
1 / 1 / 0
Регистрация: 04.08.2021
Сообщений: 193
08.04.2022, 17:43  [ТС]
Вот скрин из wireshark - пакеты из другой сети приходят как нужно, на нужный порт
Миниатюры
Сокет для получения udp пакетов с определенным портом  
0
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
08.04.2022, 19:18
Цитата Сообщение от Horwood Посмотреть сообщение
Отправка пакетов, которые мне нжно принять происходит на другой машине из другой сети.
Вполне возможно, что ваша проблема исходит из настроек сети, а не из программного кода... Можете сначала протестировать свой код на одной машине. Если прием/отправка будет работать, значит проблема не в коде приема/отправки данных.
0
 Аватар для Annemesski
2670 / 1333 / 479
Регистрация: 08.11.2016
Сообщений: 3,679
11.04.2022, 08:31
Horwood, в блокирующем режиме тоже не принимает сообщения?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
11.04.2022, 08:31
Помогаю со студенческими работами здесь

Один TCP сокет для отправки и принятия пакетов
Добрый день. Дана задача написать одну программу, которая будет запущена на двух машинах в разных сетях.Эта программа должна...

Написать программу для приема UDP пакетов
Всем доброго времени суток! Мне необходимо написать программу, которая принимала бы udp пакеты от устройства из локальной сети. В качестве...

Программа для получения пакетов данных
Народ подскажите мануалы инфу ссылки, да вообще хоть чтонибудь... Хочу напрогать приложение которое будет показывать всю информацию...

Использование mmap() для получения/отправки через сокет
Есть сокет fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)) Предполагается сделать setsockopt с параметрами...

Утилита для получения статической информации по протоколам UDP, TCP, ICMP, IP.
Т. е. надо вывести статическую инфу аналогочную, получаемую при вызове netstat -s в cmd... Может кто реализовывал что-то подобное, или...


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

Или воспользуйтесь поиском по форуму:
14
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Access
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru