Форум программистов, компьютерный форум, киберфорум
Наши страницы
C++ Qt
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.62/13: Рейтинг темы: голосов - 13, средняя оценка - 4.62
Xantrax
19 / 19 / 2
Регистрация: 28.11.2012
Сообщений: 328
1

QUdpSocket, прием датаграммы и преобразование полученного

29.11.2012, 00:22. Просмотров 2422. Ответов 10
Метки нет (Все метки)

Здравствуйте уважаемые форумчане, совсем недавно в программировании, а уж тем более в Qt...
В общем, есть игра, которая шлет с частотой в 1hz, по протоколу UDP, в сеть 127.0.0.1, один параметр - скорость. Скорость шлется в бинарном коде с типом int.
Я написал клиент:
Забиндил udpsocket на порт, на который приходит датаграмма...
Проверил wireshark, приходит ровно 8 байт, и ровно то число (если перевести с двоичного в десятичное, что показывается в игре).
Далее, принимаю датаграмму.
C++ (Qt)
1
2
3
4
5
6
void Widget :: pendingdatagram()
{
QBytearray datagram; // Беру массив байтов;
datagram.resize(udpsocket->pendingDatagram.size()); // изменяю размер под размер приходящей датаграммы.
udpsocket->readDatagram(datagram.data(), datagram.size()); // собственно принимаю(записываю) датаграмму из сокета.
}
А теперь вопрос: Как вывести число из датаграммы, ну хотя бы в qDebug() << ???

Как это делаю я? (Делаю наверняка не правильно, потому что что-то не так)

C++ (Qt)
1
2
3
int mydata;
mydata=datagram.at(3); //почему я беру только последний байт? ведь в инте их 4!
qDebug() << mydata;
В результате что получается? Я вывожу окно клиента на один монитор,а в игре начинаю лететь, скорость постепенно возрастает и вроде как выводится верное значение, но как только скорость достигает 128, она приобретает знак "-" и начинает убывать!(((
Я 100% уверен, что я не правильно обрабатываю бинарный код, который я записал в QByteArray, но как обработать его не понимаю...((

 Комментарий модератора 
Используем теги для вставки кода в свои сообщения.

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

0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
29.11.2012, 00:22
Ответы с готовыми решениями:

QUdpSocket чат. Отсылка/прием сообщений
Доброго времени суток, уважаемые форумчане! Пишу простенький чат. Описание...

Разбиение на датаграммы
Приветствую! Есть некоторая строка, достаточно длинная. Пусть 1024 символа =...

QT UDP датаграммы в двумерном char** массиве
Задача отправлять\получать файлы большого размера по протоколу UDP в системе...

QUdpSocket и инетрнет
Каким образом реализовать соединение через инет? Код с оф.доков (чуток...

QUDPSocket + moveToThread
Не могу понять как реализовать данную связку. Если писать this то он ругается,...

10
kniferko
35 / 35 / 1
Регистрация: 02.03.2012
Сообщений: 117
29.11.2012, 02:04 2
Вы берете лишь 1 байт из числа и приводите его к типу int. Пока это число не достигает значения, по-моему, 128 (так как 1 байт меняется в диапазоне от -127 до 128), все в порядке, но как только выше, то сразу -127, затем -126 и т.д.

Попробуйте так:

C++ (Qt)
1
2
3
 int *mydata;
 mydata= (int *)datagram.data();
 qDebug() << *mydata;
0
Xantrax
19 / 19 / 2
Регистрация: 28.11.2012
Сообщений: 328
29.11.2012, 09:42  [ТС] 3
Попробовал, получается каое-то неадекватное число. При реальной скорости в 3 узла (т.е. фактически 0) получается неадекватное число 50331648.
Привожу весь значимый код клиента:
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
#include "widget.h"
#include <QtNetwork/QUdpSocket>
#include <QByteArray>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
udpSocket = new QUdpSocket(this);
    udpSocket->bind(QHostAddress::LocalHost,5688);
    connect(udpSocket, SIGNAL(readyRead()),this,SLOT(processPendingDatagram()));
}
Widget::~Widget()
{
}
void Widget :: processPendingDatagram() //функция приема датаграммы
{
    while (udpSocket->hasPendingDatagrams())
    {
    QByteArray datagram;
    datagram.resize(udpSocket -> pendingDatagramSize());
    udpSocket->readDatagram(datagram.data(),
                            datagram.size());
    int *mydata;
    mydata = (int *)datagram.data();
    qDebug() << datagram.size() << *mydata ;
    }
}
В дебаге выдается: 4 50331648 //т.е. 4 это размер приходящей датаграммы, ну, а 50331648 скорость.
Вывод wireshark:
http://imglink.ru/show-image.php?id=4a31c6ffc303e44317fd0ec191c3b5fb
0
Maxim Prishchepa
Эксперт С++
1925 / 1037 / 109
Регистрация: 29.03.2010
Сообщений: 3,167
29.11.2012, 10:40 4
эм... пользуйте QDataStream и его встроенный парсер, будет гораздо проще (при условии, что источник и получатель будут на Qt написаны)

Добавлено через 2 минуты
ну и опять таки, если тупо вывести на экран, то вроде бы можно банально:
C++ (Qt)
1
qDebug() << datagram;
0
Xantrax
19 / 19 / 2
Регистрация: 28.11.2012
Сообщений: 328
29.11.2012, 12:19  [ТС] 5
C++ (Qt)
1
 qDebug() << datagram.size() << datagram ;
Выводит: 4 ", т.е. размер приходящей датаграммы и непонятные кавычки...

Над QDataStream подумаю, но так как недавно в программировании, то возникнут вопросы.
0
kniferko
35 / 35 / 1
Регистрация: 02.03.2012
Сообщений: 117
30.11.2012, 00:53 6
Очень странно. А попробуйте распечатать сам пакет в хексе, а то получается, что там явно не 3 приходит.
Вроде так:
C++ (Qt)
1
qDebug()<< datagram.toHex();
Добавлено через 1 час 24 минуты
Кажется понял. Вы отправили данные вида
Код
 0000000 00000000 00000000 00000011
А пришло в перевернутом виде (перевернут порядок байт):
Код
 0000011 00000000 00000000 00000000
Это как раз и есть число 50331648

Почитайте про сетевой порядок байт (Big-Endian) и про Интелловский порядок байт (Little-Endian)
Надеюсь, теперь Вы решите проблему
0
Xantrax
19 / 19 / 2
Регистрация: 28.11.2012
Сообщений: 328
30.11.2012, 18:08  [ТС] 7
Это как раз и есть число 50331648
А не смущают циферки скорости? Не очень ли она велика? Понятное дело, что такие данные не верны, а значит преобразование не правильное. Да, и вывод снифера wireshark я просто так что ли прилепил? Там четко написано, что приходит число 3... В данном случае я ничего не делаю в игре, т.е. стою на месте.
0
kniferko
35 / 35 / 1
Регистрация: 02.03.2012
Сообщений: 117
30.11.2012, 18:37 8
Повторю еще раз. Приходит ровно то, что вы и отправиляете, только в сетевом порядке байт. wireshark переворачивает их обратно и показывает вам уже оригинальный пакет. Я же выше расписал какой байт, где оказался...
Трудно почитать про Little-Endian и Big-Endian?
1
Xantrax
19 / 19 / 2
Регистрация: 28.11.2012
Сообщений: 328
01.12.2012, 21:11  [ТС] 9
Вопрос:
А почему вот так вот
C++ (Qt)
1
2
3
qint32 res = datagram.at(3) | datagram.at(2) | datagram.at(1) | datagram.at(0);
 qint32 litle = qFromLittleEndian(res);
 qDebug() << datagram.size() << litle;
Берет тоже один байт?
И еще вопрос, почему
C++ (Qt)
1
2
3
 qint32 res = datagram.mid(0,4);
  qint32 litle = qFromLittleEndian(res);
  qDebug() << datagram.size() << litle;
Не проходит, пишет функция mid приватна 'QByteArray::operator QNoImplicitBoolCast() const' is private и within this context. И как вообще взять сразу весь массив байтов QByteArray, вместо тогда что бы брать по одному datagram.at и присоединять их друг к другу с помощью "|" ?

эм... пользуйте QDataStream и его встроенный парсер, будет гораздо проще (при условии, что источник и получатель будут на Qt написаны)
Да, спасибо, я обязательно попробую...
0
Xantrax
19 / 19 / 2
Регистрация: 28.11.2012
Сообщений: 328
03.12.2012, 00:49  [ТС] 10
Вот у меня еще такой вопросик:
А какого типа данные приходят по сети? Ведь получается что приходит тупо бинарный код ( нули и единицы), которые не имеют никакого типа данных, да? И прежде чем осуществлять какие-то действия, нужно преобразовать эти данные к какому то типу?
0
Maxim Prishchepa
Эксперт С++
1925 / 1037 / 109
Регистрация: 29.03.2010
Сообщений: 3,167
03.12.2012, 11:32 11
Цитата Сообщение от Xantrax Посмотреть сообщение
Ведь получается что приходит тупо бинарный код ( нули и единицы), которые не имеют никакого типа данных, да?
именно, и для того, что бы не сильно уж и заморачиваться они обычно приводятся к типу QByteArray который из себя представляет массив из байт, а дальше уже сами парсите. или как я уже писал выше, используйте QDataStream и тогда можно будет сделать нечто этакое:
C++ (Qt)
1
2
3
4
5
6
7
8
streamOut << (int)(2343) << QString("text") << char('h');
...
int i;
QString str;
char ch;
streamIn >> i;
streamIn >> str;
streamIn >> ch;
0
03.12.2012, 11:32
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
03.12.2012, 11:32

QUdpSocket трабл :(
Данные отправляются, но не принимаются. В дебагере вижу, что Data имеет...

QUdpSocket + STUN
Доброго времени суток. Пару вечеров грязного времени посидел с WireShark и...

QUdpSocket и QThread
Приветствую! Задача состоит в том, чтобы класс сокета, отвечающий за...


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

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru