Russian Qt Forum

Qt => Работа с сетью => Тема начата: foxexe от Январь 18, 2010, 12:05



Название: Qt 4.4.3 msvc2008 QDataStream лишние 2-4 байта
Отправлено: 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) почему при одинаковой последовательности действий в первом случае строка принимается неормально, а во втором нет


Название: Re: Qt 4.4.3 msvc2008 QDataStream лишние 2-4 байта
Отправлено: Rcus от Январь 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


Название: Re: Qt 4.4.3 msvc2008 QDataStream лишние 2-4 байта
Отправлено: foxexe от Январь 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б?

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


Название: Re: Qt 4.4.3 msvc2008 QDataStream лишние 2-4 байта
Отправлено: Rcus от Январь 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 :)/


Название: Re: Qt 4.4.3 msvc2008 QDataStream лишние 2-4 байта
Отправлено: foxexe от Январь 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 идущих подряд  в зависимости от того как там что сработает, ведь они объединяться в одно сообщение при переслке. Или если сеть большая то также я могу получить их одновременно.



Название: Re: Qt 4.4.3 msvc2008 QDataStream лишние 2-4 байта
Отправлено: BRE от Январь 18, 2010, 14:18
А почему бы тебе не попробовать?
Код
C++ (Qt)
out << str;
out << str;
out << str;
 

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


Название: Re: Qt 4.4.3 msvc2008 QDataStream лишние 2-4 байта
Отправлено: foxexe от Январь 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]

и вторая строка получается пуста. наверняка, если все структуры я при каждом проходе цикла буду инициаллизировать заново всё пройдёт как по маслу(
в чём штука то?


Название: Re: Qt 4.4.3 msvc2008 QDataStream лишние 2-4 байта
Отправлено: foxexe от Январь 18, 2010, 14:22
А почему бы тебе не попробовать?
Код
C++ (Qt)
out << str;
out << str;
out << str;
 

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

я же говорю мне надо разделить строки, которые были отправлены в разных сообщениях, а не послать 3 строки в одном сообщении)


Название: Re: Qt 4.4.3 msvc2008 QDataStream лишние 2-4 байта
Отправлено: BRE от Январь 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;
 

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

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


Название: Re: Qt 4.4.3 msvc2008 QDataStream лишние 2-4 байта
Отправлено: foxexe от Январь 18, 2010, 14:37
Ты формируешь пакет для отправки в QDataStream.

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

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

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


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

если я сделаю

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

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

in>>str

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

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



Название: Re: Qt 4.4.3 msvc2008 QDataStream лишние 2-4 байта
Отправлено: BRE от Январь 18, 2010, 14:43
Если ты без QDataStream будешь это делать, т.е. напрямую в сокет, то конечно объединятся.
Нужно придумать самому какой то протокол, что бы указывать размер передаваемой строки или какой-то ее ограничитель. QDataStream в принципе и организует такой протокол.


Название: Re: Qt 4.4.3 msvc2008 QDataStream лишние 2-4 байта
Отправлено: foxexe от Январь 18, 2010, 14:57
Если ты без QDataStream будешь это делать, т.е. напрямую в сокет, то конечно объединятся.
Нужно придумать самому какой то протокол, что бы указывать размер передаваемой строки или какой-то ее ограничитель. QDataStream в принципе и организует такой протокол.

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


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

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


Название: Re: Qt 4.4.3 msvc2008 QDataStream лишние 2-4 байта
Отправлено: Igors от Январь 18, 2010, 15:03
А почему бы тебе не попробовать?
Код
C++ (Qt)
out << str;
out << str;
out << str;
 

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

Это действительно приятно и будет работать. Но "до первого милиционера" - ведь правильность/длина передаваемого пакта никак не контролируется  :)


Название: Re: Qt 4.4.3 msvc2008 QDataStream лишние 2-4 байта
Отправлено: BRE от Январь 18, 2010, 15:05
Это действительно приятно и будет работать. Но "до первого милиционера" - ведь правильность/длина передаваемого пакта никак не контролируется  :)
Мне нужно было полностью копипастить пример fortuneserver?  ::)
Причем, чуть ниже все расписано...


Название: Re: Qt 4.4.3 msvc2008 QDataStream лишние 2-4 байта
Отправлено: Igors от Январь 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 если данные пишутся позже?


Название: Re: Qt 4.4.3 msvc2008 QDataStream лишние 2-4 байта
Отправлено: foxexe от Январь 18, 2010, 15:43

Вот мне интересно откуда взялся size если данные пишутся позже?

вот так вот
Код
C++ (Qt)
QByteArray block;
QDataStream(&block);
quint16 size;
out<<size;//можно заменить канеш на (quint16)0;
out<<str;
out<<str;
out<<str;
out.device()->seek(0);
size=block.size()-sizeof(quint16)
out<<size;//или  сразу (quint16)((block.size()-sizeof(quint16))
 

впринципе таким обрахом вместо QString можно зафигурить любой друго тип данных главное его правильно прочитаться я так понимаю)


Название: Re: Qt 4.4.3 msvc2008 QDataStream лишние 2-4 байта
Отправлено: BRE от Январь 18, 2010, 15:51
Вот мне интересно откуда взялся size если данные пишутся позже?
Для этого нужно посмотреть выше озвученный пример.  ;)


Название: Re: Qt 4.4.3 msvc2008 QDataStream лишние 2-4 байта
Отправлено: Igors от Январь 18, 2010, 15:59
Код
C++ (Qt)
QByteArray block;
QDataStream(&block);
quint16 size;
out<<size;//можно заменить канеш на (quint16)0;
out<<str;
out<<str;
out<<str;
out.device()->seek(0);
size=block.size()-sizeof(quint16)
out<<size;//или  сразу (quint16)((block.size()-sizeof(quint16))
 
Вот это действительно расписано, все ясно. Два технических момента:

1) quint32 (вместо quint16) выглядит солиднее  :)
2) не обязательно связываться с block.size(), часто лучше использовать position() (сохраненное перед out << size)

Но эти детали не очень существенны.


Название: Re: Qt 4.4.3 msvc2008 QDataStream лишние 2-4 байта
Отправлено: foxexe от Январь 18, 2010, 16:16
1) quint32 (вместо quint16) выглядит солиднее  :)
ахахахх)) да) но я что-то тут же на форуме читал с проблемой пересылки более 40 кб, так что 32бита наверное слишком.

2) не обязательно связываться с block.size(), часто лучше использовать position() (сохраненное перед out << size)
те есть сохранить позицию до seek(0)? а почему имеено так, ведь непонятно куда указывает позишн, мошт там единичку надо вычесть, всё-таки block.size() более ориентировано на решение подобной проблемы, или вы знаете что-то что не знаю я)))

Для этого нужно посмотреть выше озвученный пример.  ;)

Это было просто ле - ...  гендарно



Название: Re: Qt 4.4.3 msvc2008 QDataStream лишние 2-4 байта
Отправлено: Igors от Январь 18, 2010, 21:39
ахахахх)) да) но я что-то тут же на форуме читал с проблемой пересылки более 40 кб, так что 32бита наверное слишком.
Ну если следовать этой логике то пакеты/файлы больше 40К передаваться не должны  :) Да хотя бы в Вашем же примере: разве QString не может быть больше 64K?

те есть сохранить позицию до seek(0)? а почему имеено так, ведь непонятно куда указывает позишн, мошт там единичку надо вычесть, всё-таки block.size() более ориентировано на решение подобной проблемы, или вы знаете что-то что не знаю я)))
Я не знаю ничего "особенного". Ну хотя бы тот же Photoshop - как он пишет свой psd файл? Да точно так же как и десятки др. хороших программ: просто IFF свободная спецификация. Общий формат

- ID тега
- число байт в теге
- сами байты/данные

Подробности уже писал здесь http://www.prog.org.ru/topic_10681_0.html (http://www.prog.org.ru/topic_10681_0.html)
Помимо прочего это дает возможность "старой" версии программы читать "новые" файлы т.к. их можно просто обойти (пропустить неизвестный тег и читать дальше).

Ну правда в талмуде (Assistant) этого нет  :)