Russian Qt Forum
Ноябрь 23, 2024, 05:05 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: При передаче через QUdpSocket первый байт неправильный  (Прочитано 5810 раз)
vulko
Гость
« : Апрель 23, 2014, 10:25 »

Столкнулся с такой проблемой, передаю данные через udp socket... точнее переделал передачу с tcp на udp.

При десериализации данных заметил кривые данные.
Дебаг помог выяснить что первый байт после десериализации неверный. В нём почему-то лежит 48 в char эквиваленте.

Можно было бы конечно первый байт забить какой-нибудь ненужной информацией... но все таки я не сторонник индусского багфикса. Хотелось бы понять причину.

Код:
typedef unsigned int uint;

struct MyStruct {
    timeval sTimeStamp;
    uint ID;
}; 

    QByteArray *block = new QByteArray;
    QDataStream out(block, QIODevice::WriteOnly);
    out.setVersion(QDataStream::Qt_4_8);
    out.setByteOrder(QDataStream::BigEndian);
    out.setFloatingPointPrecision(QDataStream::SinglePrecision);

    MyStruct *msg = new MyStruct();
    memset(msg, 1, sizeof(MyStruct));

    msg->ID = 0;
    out << msg->ID;

    udpSocket->writeDatagram(block->data(), block->size(), adr, 778);


Ну и прием:

Код:
    qDebug() << "socket data recieved: " << pUdpSocket->size() << " bytes";

    QByteArray *datagram = new QByteArray(pUdpSocket->pendingDatagramSize(), '0');

    do {
        //datagram.resize(pUdpSocket->pendingDatagramSize());
        pUdpSocket->readDatagram(datagram->data(), pUdpSocket->pendingDatagramSize());
    } while (pUdpSocket->hasPendingDatagrams());

    QDataStream in(datagram, QIODevice::ReadOnly);
    in.setVersion(QDataStream::Qt_4_8);
    in.setByteOrder(QDataStream::BigEndian);
    in.setFloatingPointPrecision(QDataStream::SinglePrecision);

    MyStruct *msg = new MyStruct();
    memset(msg, 0, sizeof(MyStruct));
    in >> msg->ID;
    evLoop->exit();

В итоге если смотреть непосредственно QByteArray'и при отправке и при получении, то они отличаются первым байтом. В нём лежит char со значением 48, вместо нуля...

Возможно я что-то делаю не так?

п.с. qt 4.8.3
Записан
OKTA
Гость
« Ответ #1 : Апрель 23, 2014, 10:37 »

48 Символ ASCII таблицы это и есть ноль вообще-то  Смеющийся
Записан
vulko
Гость
« Ответ #2 : Апрель 23, 2014, 11:18 »

48 Символ ASCII таблицы это и есть ноль вообще-то  Смеющийся

смешно канеш, но остальные то не 48, а нули, как и положено после memset'а.

в коде memset на 1ку стоит, а так вообще я на нуле тестил сперва. занулял всю структуру. писал в поток ID = 1.
QByteArray состоял нулей. Записанный инт выглядел как 3 нулевых байта и 1 байт единичка.

После передачи у меня в QByteArray лежит не 3 нуля + 1 единица, а 48, два нуля и единица.
Записан
OKTA
Гость
« Ответ #3 : Апрель 23, 2014, 11:47 »

Дал бы тестовый проект - интересно попробовать!
Записан
vulko
Гость
« Ответ #4 : Апрель 23, 2014, 14:08 »

Дал бы тестовый проект - интересно попробовать!

тестового нет.

занятно, заменил
Код:
    QByteArray *datagram = new QByteArray(pUdpSocket->pendingDatagramSize(), '0');

    do {
        //datagram.resize(pUdpSocket->pendingDatagramSize());
        pUdpSocket->readDatagram(datagram->data(), pUdpSocket->pendingDatagramSize());
    } while (pUdpSocket->hasPendingDatagrams());

    QDataStream in(datagram, QIODevice::ReadOnly);

на

Код:
    QByteArray socketData;
    socketData.resize(pUdpSocket->pendingDatagramSize());
    pUdpSocket->readDatagram(socketData.data(), socketData.size());

    QDataStream in(&socketData, QIODevice::ReadOnly);

и заработало. однако мусорные значения все ещё прилетают, но теперь хотя бы есть и правильные...

как писал ещё Пушкин... "умом QT мне не понять..."
тот же самый код, тока QByteArray теперь на стэке живет а не в куче... что за хрень...
Записан
OKTA
Гость
« Ответ #5 : Апрель 23, 2014, 14:22 »

Код:
QByteArray *datagram = new QByteArray(pUdpSocket->pendingDatagramSize(), '0');
Кажется вот, где собака порылась! Не обратил сразу внимания. Вот эта операция не обнуляет, а забивает 48 в каждый байт массива, т.к. 'X' - это int значение от символа Х.
Поставь просто
Код:
QByteArray *datagram = new QByteArray(pUdpSocket->pendingDatagramSize(), 0);
и должно заработать как надо!
Записан
vulko
Гость
« Ответ #6 : Апрель 23, 2014, 15:05 »

Код:
QByteArray *datagram = new QByteArray(pUdpSocket->pendingDatagramSize(), '0');
Кажется вот, где собака порылась! Не обратил сразу внимания. Вот эта операция не обнуляет, а забивает 48 в каждый байт массива, т.к. 'X' - это int значение от символа Х.
Поставь просто
Код:
QByteArray *datagram = new QByteArray(pUdpSocket->pendingDatagramSize(), 0);
и должно заработать как надо!


короче убрал я этот код, как и писал, заменил на другой.
добавил также movetothread(this) в конструктор класса который работает с сокетом и наследуется от qthread, чтобы все слоты также вызывались в отдельном потоке.
вообще все это movetothread это отдельная сказка... я уже оценил тупость архитекторов QT... ну да ладно, не о них речь.

теперь проблема другая на горизонте. каждый раз после моего пакета прилетает мне ещё один пакет с небольшим размером и с магическими цифрами... в виде float'а.
Код:
socket data recieved:  1  bytes   datagramm:  1 
socket data recieved:  86  bytes   datagramm:  86
socket data recieved:  3  bytes   datagramm:  3
socket data recieved:  86  bytes   datagramm:  86
socket data recieved:  4  bytes   datagramm:  4
socket data recieved:  86  bytes   datagramm:  86
socket data recieved:  2  bytes   datagramm:  2
socket data recieved:  86  bytes   datagramm:  86
socket data recieved:  2  bytes   datagramm:  2
socket data recieved:  86  bytes   datagramm:  86
socket data recieved:  3  bytes   datagramm:  3
socket data recieved:  86  bytes   datagramm:  86
socket data recieved:  3  bytes   datagramm:  3
socket data recieved:  86  bytes   datagramm:  86
socket data recieved:  3  bytes   datagramm:  3
socket data recieved:  86  bytes   datagramm:  86
socket data recieved:  3  bytes   datagramm:  3
socket data recieved:  86  bytes   datagramm:  86
socket data recieved:  5  bytes   datagramm:  5
socket data recieved:  86  bytes   datagramm:  86
socket data recieved:  5  bytes   datagramm:  5
socket data recieved:  86  bytes   datagramm:  86
socket data recieved:  5  bytes   datagramm:  5
socket data recieved:  86  bytes   datagramm:  86
socket data recieved:  7  bytes   datagramm:  7
socket data recieved:  86  bytes   datagramm:  86
socket data recieved:  7  bytes   datagramm:  7

что это за хрень, я без понятия...

идея работы у меня такая - я шлю на сервер float, он мне отвечает структурой.

соотв у меня есть класс в клиенте где есть qupdsocket.
чтобы readyRead срабатывал на пакеты на определенный порт, я делаю на клиенте
    pUdpSocket->bind(ipAddress, 54002);

серверу я шлю данные постоянно (в data лежит float)
    pUdpSocket->writeDatagram(data, ipAddress, 54001);

а у сервера соотв. привзяка к своему порту:
    pSrvUdpSocket->bind(ipAddress, 54001);

когда сервер получает пакет с float'ом, он отвечает пакетом с сериализованной структурой.

но блин у меня каждый пакет со структурой сопровождается пакетом с float'ом на клиенте, хотя сервер его не слал!
что за полтергейст...

причем я добавил логирование и это другие float'ы... откуда они?!
что это за пакеты вообще блин!!! я уже задрался с кривостями QT. брошу все нах буду на жабе писать лучше...)

Код:
sent  0 
sent  1.8
get:  0
sent  36
sent  72
get:  0
sent  106.2
sent  142.2
get:  0
sent  176.4
sent  210.6
get:  0
sent  244.8
sent  279
get:  0
sent  313.2
sent  349.2
get:  0
sent  23.3996
sent  61.1996
get:  1.8
sent  95.3996
sent  131.4
get:  36
sent  165.6
sent  199.8
get:  72
sent  235.8
sent  270
get:  106.2
sent  304.2
sent  340.199
get:  142.2
sent  16.1992
sent  52.1992
get:  176.4
sent  89.9992
sent  124.199
get:  210.6
sent  158.399
sent  192.599
get:  244.8
sent  226.799
sent  264.599
get:  279
sent  298.799
sent  331.199
get:  313.2
sent  3.5988
sent  37.7988
get:  349.2
sent  71.9988
sent  106.199
get:  23.3996
sent  140.399
sent  176.399
get:  61.1996
sent  210.599
sent  244.799
get:  95.3996
sent  280.799
sent  307.799
get:  131.4
sent  336.599
sent  10.7984
get:  165.6
sent  46.7984
sent  82.7984
get:  199.8
sent  116.998
sent  151.199
get:  235.8
sent  187.199
sent  224.999
get:  270
sent  259.199
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #7 : Апрель 23, 2014, 15:15 »

я уже задрался с кривостями QT.
Вместе с Qt идут примеры, там есть две маленьких программки broadcastsender и broadcastreceiver. Соберите их и проверьте, будут ли они у вас работать? Если будут, то не нужно здесь поливать Qt, а нужно учить язык и сам фреймфорк. C++ не прощает ошибок, это не жаба. Ошиблись чуть и будет падать и тупить.

брошу все нах буду на жабе писать лучше...)
Вы нас так не пугайте.
Записан
vulko
Гость
« Ответ #8 : Апрель 23, 2014, 15:46 »

я уже задрался с кривостями QT.
Вместе с Qt идут примеры, там есть две маленьких программки broadcastsender и broadcastreceiver. Соберите их и проверьте, будут ли они у вас работать? Если будут, то не нужно здесь поливать Qt, а нужно учить язык и сам фреймфорк. C++ не прощает ошибок, это не жаба. Ошиблись чуть и будет падать и тупить.

брошу все нах буду на жабе писать лучше...)
Вы нас так не пугайте.

Примеры это все хорошо, но как всегда от реальности они далеко. Во-первых, в этих примерах используется мультикаст, а, во-вторых... а во-вторых, как обычно примеры слишком примитивны что-бы ответить на многие вопросы.
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #9 : Апрель 23, 2014, 15:50 »

Примеры это все хорошо, но как всегда от реальности они далеко. Во-первых, в этих примерах используется мультикаст, а, во-вторых... а во-вторых, как обычно примеры слишком примитивны что-бы ответить на многие вопросы.
Они доказывают главное: виноват не Qt, а руки.
И пока вы в этом не признаетесь самому себе, ничего получаться не будет. Подмигивающий
Вы думаете вы первый у кого что-то не работает и он винит в этом компилятор, Qt, QtCreator, компьютер.... Поищите по форуму их тысячи, но как правило всегда оказывалось, что виноваты авторы, а не инструменты. Улыбающийся
Записан
OKTA
Гость
« Ответ #10 : Апрель 23, 2014, 16:15 »

Уже кстати давно надо банить за QT  Смеющийся
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.05 секунд. Запросов: 22.