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

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

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: Qt 4.4.3 msvc2008 QDataStream лишние 2-4 байта  (Прочитано 10147 раз)
foxexe
Гость
« : Январь 18, 2010, 12:05 »

Записываю в сокет как в примере fortune server

Код:
	
QString str("peter");
QByteArray block;
QDataStream out(&block,QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_4_0);
out<<a<<str;
out.device()->seek(0);
out<<(quint16)(block.size()-sizeof(qint16));//в счётчик записано 14 байт ,а block.size() тоже 16 байт
this->write(block);//передалось нормально  и отобразилось на аля fortune client нормально

почему получается что строка из 5 символов занимает 14 байт, хотя должна вроде 12, но приёмник читает нормально(приёмник работает по принципу fortune client)
сразу в теле фой же функции пытаюсь отправить вторуб строку
Код:
	str=QString("sos");
block.clear();
i=block.size();//i=0
out<<a<<str;
t=block.size();//t=14!!!!!
out.device()->seek(0);
t=block.size()-sizeof(qint16);//t=12
out<<(quint16)(t);
this->write(block);// передалось и не отобразилось

получается во втором случае получаются аж 4 либшних байта вот таким образом:
1)откуда беруться 2 лишних байта в первом случае
2) откуда беруться 4 лишних байта во втором случае
3) почему при одинаковой последовательности действий в первом случае строка принимается неормально, а во втором нет
Записан
Rcus
Гость
« Ответ #1 : Январь 18, 2010, 12:35 »

Что или кто есть "a"? © Вангеры
Почему вы считаете что строка из 5 символов должна занимать 12 байт при записи в QDataStream если согласно Assistant->Format of the QDataStream Operators
Цитировать
QString   
If the string is null: 0xFFFFFFFF (quint32)
Otherwise: The string length in bytes (quint32) followed by the data in UTF-16
Записан
foxexe
Гость
« Ответ #2 : Январь 18, 2010, 13:16 »

Что или кто есть "a"? © Вангеры
quint16 a;
впринципе тут просто как переменная quint16 и смысловой нагрузки особенно не несёт.


Почему вы считаете что строка из 5 символов должна занимать 12 байт при записи в QDataStream если согласно Assistant->Format of the QDataStream Operators
Цитировать
QString   
If the string is null: 0xFFFFFFFF (quint32)
Otherwise: The string length in bytes (quint32) followed by the data in UTF-16

мой косяк, всё понятно, но тогда вопрос ко второй части, почему тогда строка из 3 символов занимает 12 байт, хотя максимум на что она свобна 4б(quint32)+3*2б(макс размер 3х симв)=10б?

и сразу ещё вопрос, если уж строка содержит вначале свою длинну, то можно ли передатать тогда строку не в формате |длинна сообщ|сообщения| чтобы две строки в разных сообщениях не могли слиться в одну при передаче
Записан
Rcus
Гость
« Ответ #3 : Январь 18, 2010, 13:28 »

/*shrugs*/
Код
C++ (Qt)
   QByteArray block;
   QDataStream out(&block, QIODevice::WriteOnly);
   out << QString("sos");
   qFatal("block size = %d, content = %s", block.size(), block.toHex().data());
 
Код:
block size = 10, content = 000000060073006f0073

Последнее предложение не распарсил. Но мне кажется что стоит посмотреть на реальные сетевые протоколы /ну хотя бы BitTorrent :)/
Записан
foxexe
Гость
« Ответ #4 : Январь 18, 2010, 13:35 »

/*shrugs*/
Код
C++ (Qt)
   QByteArray block;
   QDataStream out(&block, QIODevice::WriteOnly);
   out << QString("sos");
   qFatal("block size = %d, content = %s", block.size(), block.toHex().data());
 
Код:
block size = 10, content = 000000060073006f0073

Последнее предложение не распарсил. Но мне кажется что стоит посмотреть на реальные сетевые протоколы /ну хотя бы BitTorrent Улыбающийся/

в первый раз всё срабатывает нормально!!! а если постоврить на тех же переменных передачу- block, out  то "sos" займёт 12 б , вот в чём вопрос

ну с битторентом вы загнули, мне просто найдо послать строку, но при условии чтобы они не могли слиться, ибо если я сделаю
write(str);
write(str);
write(str);
то на приёмнике я могу 3str идущих подряд  в зависимости от того как там что сработает, ведь они объединяться в одно сообщение при переслке. Или если сеть большая то также я могу получить их одновременно.

Записан
BRE
Гость
« Ответ #5 : Январь 18, 2010, 14:18 »

А почему бы тебе не попробовать?
Код
C++ (Qt)
out << str;
out << str;
out << str;
 

А на другой стороне принять.
Думаю ты будешь приятно удивлен.  Улыбающийся
Записан
foxexe
Гость
« Ответ #6 : Январь 18, 2010, 14:21 »

вот штука в том что если я проинициализирую для передачи второй строки все эти объекты заново(QByteArray,QDataStream) то передасться всё нормально, но при этом если приёмник работает вот так

Код
C++ (Qt)
static qint16 blockSize=0;
QString a;
emit TextOutput("Socket:ready read "+QString::number(sock->bytesAvailable())+"bytes");
QDataStream in(sock);
QByteArray block;
QDataStream tmp(&block,QIODevice::ReadOnly);
int ba;
in.setVersion(QDataStream::Qt_4_0);
while(sock->bytesAvailable()>0) // есть ещё байты что прочитать можно
{
           //фактически фортун клиент, только я тут читаю в строку определённо число байт
 
if (blockSize == 0) {
if (sock->bytesAvailable() < (int)sizeof(quint16))
return;
 
in >> blockSize;//длинна полученной строки в байтах
}
ba=sock->bytesAvailable();
if (ba < blockSize)
return;
block=sock->read(blockSize);//читаем длинну строки в байтах
tmp.setVersion(QDataStream::Qt_4_0);
tmp>>a;//и запихиваем в QString
emit TextOutput("Socket:recv "+QString::number(blockSize)+" bytes="+a);
ba=sock->bytesAvailable();
 
 
//sock->write(a.toLocal8Bit());
blockSize=0;
}
 
}
это фактически fortune client, только он может разъединять сообщения если они пришли одновременно. Таким образом  если приходят "str1" и "str2" указанным в теме способом(отправились они нормально), я получаю на выходе приёмника
Цитировать
Socket: ready read 28 bytes
Socket: recv 12
bytes = str1
Socket: recv 12[/quote] bytes =
[/quote]

и вторая строка получается пуста. наверняка, если все структуры я при каждом проходе цикла буду инициаллизировать заново всё пройдёт как по маслу(
в чём штука то?
Записан
foxexe
Гость
« Ответ #7 : Январь 18, 2010, 14:22 »

А почему бы тебе не попробовать?
Код
C++ (Qt)
out << str;
out << str;
out << str;
 

А на другой стороне принять.
Думаю ты будешь приятно удивлен.  Улыбающийся

я же говорю мне надо разделить строки, которые были отправлены в разных сообщениях, а не послать 3 строки в одном сообщении)
Записан
BRE
Гость
« Ответ #8 : Январь 18, 2010, 14:30 »

Ты формируешь пакет для отправки в QDataStream.

Код
C++ (Qt)
QString str = tr( "sos" );
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
out << size;   // Размер блока как в примере
out << QString( "Str1" );
out << QString( "Str2" );
out << QString( "Str3" );
// Отправка block
 

На другой стороне получаешь весь блок целиком и делаешь:
Код
C++ (Qt)
// Чтение размера блока
// Ожидание и чтение всего блока
QString str1, str2, str3;
in >> str1 >> str2 >> str3;
 

И ты получишь нужные тебе строки...

А из разных сообщение ты и так получишь разные строки.
Записан
foxexe
Гость
« Ответ #9 : Январь 18, 2010, 14:37 »

Ты формируешь пакет для отправки в QDataStream.

На другой стороне получаешь весь блок целиком и ...

И ты получишь нужные тебе строки...

А из разных сообщение ты и так получишь разные строки.


нет нет нет, вы не поняли!

если я сделаю

sock.write("string1");
sock.write("string2");
sock.write("string3");

то на приёмнике если я сделаю

in>>str

то получу str="string1string2string3", а я стремлюсь чтобы этого не было!

конечно можно попробовать flush() сделать, но если на приёмнике они придут одновременно, то они объединяться??? я щас попробую, и в основном меня интересует почему вот такие ошибки

Записан
BRE
Гость
« Ответ #10 : Январь 18, 2010, 14:43 »

Если ты без QDataStream будешь это делать, т.е. напрямую в сокет, то конечно объединятся.
Нужно придумать самому какой то протокол, что бы указывать размер передаваемой строки или какой-то ее ограничитель. QDataStream в принципе и организует такой протокол.
Записан
foxexe
Гость
« Ответ #11 : Январь 18, 2010, 14:57 »

Если ты без QDataStream будешь это делать, т.е. напрямую в сокет, то конечно объединятся.
Нужно придумать самому какой то протокол, что бы указывать размер передаваемой строки или какой-то ее ограничитель. QDataStream в принципе и организует такой протокол.

да QDataStream однако и правда их умеет разбивать, только что попробовал))) так что спасибо, не знаю как я провафлился так


но всё-таки почему при отсылке/отправке если не проиниаллизировать всё заново то получаются какие-то траблы  я не понимаю.

но проблема решена в общем, я просто сначала пользовался readAll(), и вообще не хотел пользоваться QDataStream, отсюда я пропустил то что QDataStread сама их разаобьёт по чести, отсюда такая сложность в пересылке с кстати существующим полем - длинна строки. это у меня по старой доброй юниксовской памяти просто, там же надо было как-то получать размер буфера) тут таки проще
спасибо
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #12 : Январь 18, 2010, 15:03 »

А почему бы тебе не попробовать?
Код
C++ (Qt)
out << str;
out << str;
out << str;
 

А на другой стороне принять.
Думаю ты будешь приятно удивлен.  Улыбающийся

Это действительно приятно и будет работать. Но "до первого милиционера" - ведь правильность/длина передаваемого пакта никак не контролируется  Улыбающийся
Записан
BRE
Гость
« Ответ #13 : Январь 18, 2010, 15:05 »

Это действительно приятно и будет работать. Но "до первого милиционера" - ведь правильность/длина передаваемого пакта никак не контролируется  Улыбающийся
Мне нужно было полностью копипастить пример fortuneserver?  Строит глазки
Причем, чуть ниже все расписано...
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #14 : Январь 18, 2010, 15:27 »

Причем, чуть ниже все расписано...
А что собственно расписано?

Код
C++ (Qt)
QString str = tr( "sos" );
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
out << size;   // Размер блока как в примере
out << QString( "Str1" );
out << QString( "Str2" );
out << QString( "Str3" );
 
Вот мне интересно откуда взялся size если данные пишутся позже?
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


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