Вывод ответа, полученного по 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 шт):
Абсолютно не понятно, что и как отправляется, поэтому, напишу несколько способов как это можно вывести, а Вы уже пробуйте.
Для начала посмотрим на эту строку
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?