Форум программистов, компьютерный форум, киберфорум
Наши страницы

Qt

Войти
Регистрация
Восстановить пароль
 
Рейтинг: Рейтинг темы: голосов - 16, средняя оценка - 4.94
Xantrax
19 / 19 / 1
Регистрация: 28.11.2012
Сообщений: 328
#1

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

29.11.2012, 00:22. Просмотров 2283. Ответов 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, прием датаграммы и преобразование полученного (C++ Qt):

QUdpSocket чат. Отсылка/прием сообщений - C++ Qt
Доброго времени суток, уважаемые форумчане! Пишу простенький чат. Описание идеи (пригодится для понимания структуры программы):Идея...

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

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

QUdpSocket readyRead - C++ Qt
Здравствуйте, люди добрые. Уже месяц мучаюсь с одной проблемой. Пишу курсовую работу на Qt: голосовая связь по протоколу UDP....

QUdpSocket и QThread - C++ Qt
Приветствую! Задача состоит в том, чтобы класс сокета, отвечающий за скачивания информации работал в отдельном потоке QThread. У...

QUdpSocket и инетрнет - C++ Qt
Каким образом реализовать соединение через инет? Код с оф.доков (чуток переписанный) через localhost работает, а как через интернет...

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 / 1
Регистрация: 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
Эксперт С++
1924 / 1036 / 74
Регистрация: 29.03.2010
Сообщений: 3,167
29.11.2012, 10:40 #4
эм... пользуйте QDataStream и его встроенный парсер, будет гораздо проще (при условии, что источник и получатель будут на Qt написаны)

Добавлено через 2 минуты
ну и опять таки, если тупо вывести на экран, то вроде бы можно банально:
C++ (Qt)
1
qDebug() << datagram;
0
Xantrax
19 / 19 / 1
Регистрация: 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 / 1
Регистрация: 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 / 1
Регистрация: 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 / 1
Регистрация: 28.11.2012
Сообщений: 328
03.12.2012, 00:49  [ТС] #10
Вот у меня еще такой вопросик:
А какого типа данные приходят по сети? Ведь получается что приходит тупо бинарный код ( нули и единицы), которые не имеют никакого типа данных, да? И прежде чем осуществлять какие-то действия, нужно преобразовать эти данные к какому то типу?
0
Maxim Prishchepa
Эксперт С++
1924 / 1036 / 74
Регистрация: 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 - C++ Qt
Есть серверное приложение, которое посылает большое количество дынных на udp-socket. Вывожу отладочные сообщения, которые говорят, что...

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

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

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


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

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

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