Вывод ответа, полученного по UDP

В этой части кода не пойму, как вывести на консоль текст в читаемом виде. Сообщение отправляю. Оно доходит, но на консоль не выводится.

#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <fcntl.h>

struct message {
    double test;
};
        
int main()
{
    //создание сокета
    int handle = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
    if ( handle <= 0 )
    {
        printf( "failed to create socket\n" );
        return false;
    }
    
    unsigned int a = 10;
    unsigned int b = 100;
    unsigned int c = 0;
    unsigned int d = 50;
    unsigned short port = 10000;
    unsigned int destination_address = ( a << 24 ) | ( b << 16 ) | ( c << 8 ) | d;
    unsigned short destination_port = port;
    sockaddr_in address;
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = htonl( destination_address );
    address.sin_port = htons( destination_port );

    if ( bind( handle, (const sockaddr*) &address, sizeof(sockaddr_in) ) < 0 )
    {
        printf( "failed to bind socket\n" );
        return false;
    }

    while ( true )
    {
        unsigned char packet_data[256];
        unsigned int maximum_packet_size = sizeof( packet_data );

        sockaddr_in from;
        socklen_t fromLength = sizeof( from );

        int received_bytes = recvfrom( handle, (char*)packet_data, 10,
            0, (sockaddr*)&from, &fromLength );



        // с этим местом проблема
        std::cout << packet_data;
    
        //if ( received_bytes <= 0 )
            break;

        unsigned int from_address = ntohl( from.sin_addr.s_addr );
        unsigned int from_port = ntohs( from.sin_port );

    }
    return 0;
}


Ответы (1 шт):

Автор решения: KoVadim

Абсолютно не понятно, что и как отправляется, поэтому, напишу несколько способов как это можно вывести, а Вы уже пробуйте.

Для начала посмотрим на эту строку

int received_bytes = recvfrom( handle, (char*)packet_data, 10,
        0, (sockaddr*)&from, &fromLength );

тут есть одна проблема - явно захардкожено число 10 (размер буфера). если с той стороны будет отправляется буфер большего размера, то ничего не получите (кроме ошибки:) ). Поэтому, лучше буфер сделать явно побольше и это размер использовать, тем более он там уже есть - maximum_packet_size

int received_bytes = recvfrom( handle, (char*)packet_data, maximum_packet_size ,
        0, (sockaddr*)&from, &fromLength );

а сам буфер лучше сделать около 8 килобайт (8096) - этого обычно хватит для тестовых целей.

Следующий этап - нужно проверять, а не было ли ошибок. Для этого сразу после каждой сетевой функции добавьте такое

int code = WSAGetLastError();
if (code != 0) {
  std::cout << "error code " << code << "\n";
}

рекомендую на начальном этапе реально после каждой сетевой функции вставлять. и потом сверять код ошибки по https://docs.microsoft.com/en-us/windows/win32/winsock/windows-sockets-error-codes-2

теперь попробуем распечатать буфер в хекс виде

for (int i = 0; i < received_bytes ; i++) {
    std::cout
        << std::setfill('0') // что бы нолик был в начале
        << std::setw(2) // и два символа шириной
        << std::hex // и в хексе
        << (int)packet_data[i] // и само число
        << ' ';
    }

и теперь будет красивый вывод 01 00 05 ff

а вот второй способ

for (int i = 0; i < received_bytes; i++) {
    unsigned char c = packet_data[i];
    if (c >= ' ' && c <= 0x7f) { // символ печатный
        std::cout << c; // выведем его
    } else {
        std::cout << '.'; // а иначе точка как заполнитель
    }
}

и теперь можно будет "увидеть строку". Да, если там utf-8 или кириллица в cp1251, то так просто не увидеть, но кто мешает поправить if?

→ Ссылка