Russian Qt Forum

Qt => Работа с сетью => Тема начата: max1983 от Июль 21, 2009, 22:06



Название: QTcpSocket и QXmlStreamWriter
Отправлено: max1983 от Июль 21, 2009, 22:06
Вот такой кусок кода для записи XML в сокет
Код:
QTcpSocket * Sok = new QTcpSocket();
Sok->connectToHost("127.0.0.1",5000);
 
    QXmlStreamWriter *  wr = new QXmlStreamWriter(Sok);
   
      wr->writeStartElement("RootValue");//
   
wr->writeStartElement("Element_Value0");
wr->writeEndElement();

wr->writeStartElement("Element_Value1");
wr->writeEndElement();

wr->writeStartElement("Element_Value2");
wr->writeEndElement();

wr->writeEndElement();

если пишу
Цитировать
Sok->close();
То данные успешно получает сервер.
но сокет увы закрыт а мне с него еще прочитать данные надо

если пишу
Цитировать
Sok->flush();
то на другом конце ерор "не видит начального элемента" или их больше одного проверить нет как.

ну и что сделать чтоб данные с сокета отправились а сокет не закрылся?
у самого QXmlStreamWriter вроде функций таких нема но лучше перепроверите сами, так как я ламо еще тот. ;D

так как QXmlStreamWriter прибамбас новый(This class was introduced in Qt 4.3.) самплесов в сети по этому поводу просто нет.



Название: Re: QTcpSocket и QXmlStreamWriter
Отправлено: ритт от Июль 21, 2009, 22:25
да уж, в преддверии 4.6 версия 4.3 ещё довольно свежая...

Прямо в начале секции Detailed Description официальной документации по классу QXmlStreamWriter приведён пример:

Код:
     QXmlStreamWriter stream(&output);
     stream.setAutoFormatting(true);
     stream.writeStartDocument();
     ...
     stream.writeStartElement("bookmark");
     stream.writeAttribute("href", "http://www.qtsoftware.com/");
     stream.writeTextElement("title", "Qt Home");
     stream.writeEndElement(); // bookmark
     ...
     stream.writeEndDocument();


Название: Re: QTcpSocket и QXmlStreamWriter
Отправлено: max1983 от Июль 22, 2009, 00:13
Конструктивный ответ:
Да, этот пример я не обнаружил(Detailed Description )
Да ета фишка мне не помогла так как совсем не похожа на то что мне надо.
И мой код не отличается от приведенного!
Если ты про дополнительные теги вроде writeStartDocument и setAutoFormatting что сними что без них разницы нет.
Да ты не побывал писать в поток сокета XML иначе понял мою проблему.




Название: Re: QTcpSocket и QXmlStreamWriter
Отправлено: Blayder от Июль 22, 2009, 00:32
Цитировать
void QXmlStreamWriter::writeStartDocument ( const QString & version )

Writes a document start with the XML version number version.

See also writeEndDocument().
Цитировать
void QXmlStreamWriter::writeEndDocument ()

Closes all remaining open start elements and writes a newline.

See also writeStartDocument().

http://doc.trolltech.com/4.5/qxmlstreamwriter.html#writeEndDocument

Может быть он на это тебе намекал... то, чего в твоем коде нету?
Я сам этого не пробовал да и тоже новичек...
Но наскоко я считаю, ваша проблема кроется в том, что вы не завершаете запись документа в стриме... собсна оттуда и ноги проблемы...


Название: Re: QTcpSocket и QXmlStreamWriter
Отправлено: f-r-o-s-t от Июль 22, 2009, 01:13
В примере быстрее код записи в файл а не в сокет. Спорим?

Ну допустим в файл, что это меняет ?


Название: Re: QTcpSocket и QXmlStreamWriter
Отправлено: max1983 от Июль 22, 2009, 01:28

Цитировать
что это меняет ?

А как ты думаешь?
Я думаю что: ты думаешь что ничего это не меняет.
Я также полагаю: ты знаешь что по етому поводу думаю я, а точнее я думаю что ето все меняет и пример мне не годится.
Ну раз ты все равно спросил значит ты хочешь доказательств или здравых аргументов.
Воспользуйся своим советом
Цитировать
прочитать внимательно
Нет ты не подумай совет просто отличный!
У меня например 2 книги на руском по QT и 2 на Eng и там нет примеров по QXmlStreamWriter.
Видишь я сам следую этому правилу.

кроче.. просто не работает.
Я не отрицаю что мне не хватает знаний в QT :o


Название: Re: QTcpSocket и QXmlStreamWriter
Отправлено: max1983 от Июль 22, 2009, 01:44
Ладно давай еще раз, тебе нужно что бы сокет не закрылся, а данные отправились ?

Ага.
Местный Священник замял все прикольные фразы в топике.
И я вроде как нашел решение проблемы.
Пока говорить рано но всегда интересно знать что думают остальные лысые с тату.
мнение ежиков интересует меньше.
Я все образно никого не оскорбляю...


Название: Re: QTcpSocket и QXmlStreamWriter
Отправлено: pastor от Июль 22, 2009, 02:02
И я вроде как нашел решение проблемы.

И что за решение?


Название: Re: QTcpSocket и QXmlStreamWriter
Отправлено: max1983 от Июль 22, 2009, 02:04
Цитировать
И что за решение?
Обязательно отпишусь как буду уверен.


Название: Re: QTcpSocket и QXmlStreamWriter
Отправлено: ритт от Июль 22, 2009, 12:48
заглянул в сорцы - writeStartDocument / writeEndDocument нужны для записи well-formed xml
и, исходя из твоей тарабарщины:
Цитировать
если пишу
Цитировать
Sok->flush();
то на другом конце ерор "не видит начального элемента" или их больше одного проверить нет как.
сниппет должен завершаться так:
Код:
     stream.writeEndDocument();

     output.flush();


Название: Re: QTcpSocket и QXmlStreamWriter
Отправлено: max1983 от Июль 22, 2009, 15:35
Цитировать
и, исходя из твоей тарабарщины:
О! Ты еще кода моего не видел  ;D вот там то точно разобраться не просто.
Но специально для тебя я облегчил его восприятие и показываю как не работает.
Код:

    QTcpSocket * Sok = new QTcpSocket();
    Sok->connectToHost("127.0.0.1",5000);
 
    QXmlStreamWriter *  wr = new QXmlStreamWriter(Sok);
    QXmlStreamReader * rd = new QXmlStreamReader(Sok);
   
   

   
    wr->setAutoFormatting(true);
    wr->writeStartDocument();
    wr->writeStartElement("ValueStart");//Root
   
wr->writeStartElement("ValueNext");
wr->writeEndElement();

wr->writeStartElement("ValueNext2");
wr->writeEndElement();

wr->writeStartElement("ValueNext3");
wr->writeEndElement();

wr->writeEndElement();
wr->writeEndDocument();//End Root
Sok->flush();


И при подобном подходе вылазит ошибка на другом конце провода.
как я и писал.
Но если заменить flush на close ошибки нет.
Ну раз ты даже сырцы всковернул ты явно не думаешь что моя тарабарщина без смысла.
Или хочешь что-то доказать.

так как обещал показать как оно должно работать привожу кусок кода который работает на 16,66666666666667%
Почему цифра такая загадочная путь ответить ежик.
Код:
   QTcpSocket * Sok = new QTcpSocket();
    Sok->connectToHost("127.0.0.1",5000);
 
   wr = new QXmlStreamWriter(Sok);
   rd = new QXmlStreamReader(Sok);
   connect(Sok, SIGNAL(readyRead()),this, SLOT(IncomingDataXML()));

  wr->writeStartElement("ValueStart");//Root
   
wr->writeStartElement("ValueNext");
wr->writeEndElement();

wr->writeStartElement("ValueNext2");
wr->writeEndElement();

wr->writeStartElement("ValueNext3");
wr->writeEndElement();

wr->writeEndElement();


Все кто хочет юзать такие фишки(QXmlStreamWriter & QXmlStreamReader) учтите что считывание происходит калбаком в слот
а запись как пожелаете, видать сокеты не асинхронные.

Если найду что добавить обязательно добавлю в етот топ.


Название: Re: QTcpSocket и QXmlStreamWriter
Отправлено: BigZ от Июль 22, 2009, 16:22
А на функцию IncomingDataXML можно взглянуть?


Название: Re: QTcpSocket и QXmlStreamWriter
Отправлено: max1983 от Июль 22, 2009, 16:33
А на функцию IncomingDataXML можно взглянуть?
Хотя я ее еще не закончил.. чтож щедрости моей нет предела
Код:
void MainWindowImpl::IncomingDataXML()
{



while(!rd->atEnd())
{

rd->readNext();

textEdit->append(rd->tokenString());

switch(rd->tokenType())
{


case QXmlStreamReader::NoToken:
{

}
break;

case QXmlStreamReader::Invalid:
{

}
break;

case QXmlStreamReader::StartDocument:
{

}
break;

case QXmlStreamReader::EndDocument:
{

}
break;

case QXmlStreamReader::StartElement:
{
textEdit->append("Name: "+  rd->name().toString() + " Value: " + rd->readElementText());
}
break;

case QXmlStreamReader::EndElement:
{


}
break;

case QXmlStreamReader::Characters:
{

}
break;

case QXmlStreamReader::Comment:
{

}
break;

case QXmlStreamReader::DTD:
{

}
break;

case QXmlStreamReader::EntityReference:
{

}
break;

case QXmlStreamReader::ProcessingInstruction:
{

}
break;




}




}

}

кстати если кто здесь видит не правильный подход
и у него есть идеи почему 1 раз из 6 запросов данные приходя без проблем а а остальные
разы ошибка у rd->atEnd() ---------->>>> QXmlStreamReader::UnexpectedElementError
Принимаются любые даже безумные идеи.
Да! Размер входящего XML 60 кб он не меняется и другой клиент написанный на .Net всегда принимал без проблем.


Название: Re: QTcpSocket и QXmlStreamWriter
Отправлено: BigZ от Июль 22, 2009, 16:50
When atEnd() and hasError() return true and error() returns PrematureEndOfDocumentError, it means the XML has been well-formed so far, but a complete XML document has not been parsed. The next chunk of XML can be added with addData(), if the XML is being read from a QByteArray, or by waiting for more data to arrive if the XML is being read from a QIODevice. Either way, atEnd() will return false once more adata is available.


Ты уверен, что у тебя ошибка UnexpectedElementError а не PrematureEndOfDocumentError?
Судя по твоей проблеме у тебя именно PrematureEndOfDocumentError, а это говорит о том что данных доступных для чтения не достаточно для завершени XML конструкции. В этом случае выходи из
IncomingDataXML, на след. заходе дочитаешь оставшиеся.


Название: Re: QTcpSocket и QXmlStreamWriter
Отправлено: max1983 от Июль 22, 2009, 19:20
Ты уверен, что у тебя ошибка UnexpectedElementError а не PrematureEndOfDocumentError?
Судя по твоей проблеме у тебя именно PrematureEndOfDocumentError, а это говорит о том что данных доступных для чтения не достаточно для завершени XML конструкции. В этом случае выходи из IncomingDataXML, на след. заходе дочитаешь оставшиеся.

Клевые идеи! Прям как по заказу...
Тем не менее я решил их проверить.
Сначала ты предположил что я не правильно диагностировал ошибку а потом ты сделал вид что я с етим согласился.
И так ты утверждаемый что данных слишком много чтоб за раз их можно было принять.
Значит увеличим буфер приема в сокете.
Сначала я сделал так
Цитировать
Sok->setReadBufferSize(165536);
эт не помогло.
Данные обрывались в самом начале(как и было до етого)
и текстовый бокс гласил
Цитировать
StartDocument
StartElement
Name: GAME Value:

тогда я увеличил до 111165536 -не знаю сколько ето но много!
Не помогло!

тогда решил уменьшать
и только кода поставил 20
картина хоть как-то изменилась
пришло
Цитировать
StartDocument
Invalid
StartElement
Name: GAME Value:
StartElement
Name:  Value: 1485

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

уменьшил объем данных до 5 кб
эт не помогло.

Цитировать
на след. заходе дочитаешь оставшиеся.

эт ты се как представляеш ?
у меня же QXmlStreamReader !
а если у меня несколько вложенных циклов которые что-то инициализируют.
Притом раз в 6-9 раз данные приходят нормально - разом.
Пнятно что ничего не понятно.
Ошибку определяю так
Цитировать
int z=0;

   
   while(!rd->atEnd() || (z = rd->atEnd()))
   {
      int i = rd->atEnd();
   
      
      QMessageBox::about(0,"AAAAAAAAAAAA",QString::number(z));
      

то есть циферка 1 говорит что ошибка UnexpectedElementError

Ну а на запрос
Цитировать
QMessageBox::about(0,"AAAAAAAAAAAA",rd->errorString());
вернулась фраза
Цитировать
Expected character data

Есть идеи?


Название: Re: QTcpSocket и QXmlStreamWriter
Отправлено: ритт от Июль 22, 2009, 19:34
<Nelson mode>ха-ха</Nelson mode>

в курсе, что readyRead() рассылается каждый раз, когда была получена порция данных?
пришло тебе 20 байт, а ты и рад сразу парсить...опа, а в документе было 60Кб...
!rtfm: QIODevice::waitForReadyRead


Название: Re: QTcpSocket и QXmlStreamWriter
Отправлено: ритт от Июль 22, 2009, 21:48
ключевое слово rtfm

/* на вс.случай http://en.wikipedia.org/wiki/RTFM */


Название: Re: QTcpSocket и QXmlStreamWriter
Отправлено: pastor от Июль 22, 2009, 22:27
И что с етим делать? Если поставить вместо readyRead() то не помогает.

waitForReadyRead это не сигнал. Поэтому данная замена работать не будет. Это абсолютно неадекватная замена.

IncomingDataXML также написана неверное. Откуда уверенность, что все данные прийдут за один раз? Почитай про Incremental parsing QXmlStreamReader


ЗЫ: Антилох, здесь нет форумчан "ежик" и т.п., есть Константин, запомни это! И выбирай выражения попроще - это предупреждение. Я тебя вчера отсылал почитать правила форума? Отсылал. Непонял - прочитай еще раз.


Название: Re: QTcpSocket и QXmlStreamWriter
Отправлено: max1983 от Июль 22, 2009, 22:45
Цитировать
Откуда уверенность, что все данные прийдут за один раз? Почитай про Incremental parsing QXmlStreamReader
ну иногда же приходят..
есть 2 варианта
1 все приходит
2 приходят первые 3 строчки..
Второе бывает чаще.

Ну хоть у кого то есть пример как считать все данные QXmlStreamReaderom посредством сокета?


Название: Re: QTcpSocket и QXmlStreamWriter
Отправлено: pastor от Июль 22, 2009, 22:48
ну иногда же приходят..

Ну тогда иногда твоя прога и будет работать, ничем помочь в этом случае нельзя. Это первый вариант. Второй вариант сделать чтение по-человечески, т.к. приход данных в полном объеме не гарантирован и с этим ничего не попишешь


Название: Re: QTcpSocket и QXmlStreamWriter
Отправлено: max1983 от Июль 22, 2009, 22:53
Цитировать
Ну тогда иногда твоя прога и будет работать, ничем помочь в этом случае нельзя. Это первый вариант. Второй вариант сделать чтение по-человечески, т.к. приход данных в полном объеме не гарантирован и с этим ничего не попишешь
Теряется весь смысл QXmlStreamReaderа если я не могу сериализовать данные без остановки нафиг он мне вообще сдался?
Ну представь я заполняю элементами XML в цикле свой класс.. и опа! данные закончились.
Вся идея в том чтоб когда все данные пришли начинать сериализацию и завершить ее.


Название: Re: QTcpSocket и QXmlStreamWriter
Отправлено: pastor от Июль 22, 2009, 23:17
QXmlStreamReaderа абсолютно здесь непричем. Почитай инфу про сокеты


Название: Re: QTcpSocket и QXmlStreamWriter
Отправлено: max1983 от Июль 22, 2009, 23:34
У меня появилась теория что лагает Windows 7.
Желающие протестировать есть? Пишите в ПМ.


Название: Re: QTcpSocket и QXmlStreamWriter
Отправлено: ритт от Июль 22, 2009, 23:48
хм, а при чём здесь оска?

Теряется весь смысл QXmlStreamReaderа если я не могу сериализовать данные без остановки нафиг он мне вообще сдался?
теряется весь смысл написания документации, если её не читают...

Вся идея в том чтоб когда все данные пришли начинать сериализацию и завершить ее.
дык, воспользуйся waitForReadyRead и разбирай поток порцию за порцией.
либо индусский вариант - на readyRead складывай данные в кучку, а когда данные перестанут приходить, начинай разбор


Название: Re: QTcpSocket и QXmlStreamWriter
Отправлено: max1983 от Июль 23, 2009, 00:12
Цитировать
bool QAbstractSocket::waitForReadyRead ( int msecs = 30000 )   [virtual]
Эта функция блокирует сокет, пока данные, доступные для чтения, не будут прочитаны с помощью readyRead() и соответствующий сигнал не будет послан. Эта функция имеет таймаут msecs, заданныё в миллисекундах; по умолчанию он равен 3000 мс.
Функция возвращает true, если данные доступны для чтения; в противном случае возвращается false (если произошла ошибка или прошло время таймаута).

Как по мне из выше сказанного становится понятно что данная фишка не применима.
Но я сделал попытку  и результат стал интереснее примерно  50% запросов успешно принимают XML без проблем.


Название: Re: QTcpSocket и QXmlStreamWriter
Отправлено: ритт от Июль 23, 2009, 00:42
нет, ты определённо издеваешься.

Цитировать
void QIODevice::readyRead ()   [signal]

This signal is emitted once every time new data is available for reading from the device. It will only be emitted again once new data is available, such as when a new payload of network data has arrived on your network socket, or when a new block of data has been appended to your device.

readyRead() is not emitted recursively; if you reenter the event loop or call waitForReadyRead() inside a slot connected to the readyRead() signal, the signal will not be reemitted (although waitForReadyRead() may still return true).

а можно вообще не дожидаться всего документа - примерно так:
Код
C++ (Qt)
   QTcpSocket * Sok = new QTcpSocket();
   Sok->connectToHost("127.0.0.1",5000);
 
   QXmlStreamWriter *  wr = new QXmlStreamWriter(Sok);
   QXmlStreamReader * rd = new QXmlStreamReader(Sok);
 
   wr->setAutoFormatting(true);
   wr->writeStartDocument();
  wr->writeStartElement("ValueStart");//Root
 
wr->writeStartElement("ValueNext");
wr->writeEndElement();
 
wr->writeStartElement("ValueNext2");
wr->writeEndElement();
 
wr->writeStartElement("ValueNext3");
wr->writeEndElement();
 
wr->writeEndElement();
   wr->writeEndDocument();//End Root
   Sok->flush();
 
<snip>
 
void MainWindowImpl::IncomingDataXML()
{
rd->readNext();
while(!rd->atEnd())
{
// parsing code there
// ...
 
rd->readNext();
}
}
 
добавь обработку ошибок и т.д.

upd: хмм, пропустил connect(readyRead -> IncomingDataXML)


Название: Re: QTcpSocket и QXmlStreamWriter
Отправлено: BigZ от Июль 23, 2009, 08:33
int z=0;

   
   while(!rd->atEnd() || (z = rd->atEnd()))
   {
      int i = rd->atEnd();
   
      
      QMessageBox::about(0,"AAAAAAAAAAAA",QString::number(z));
      
то есть циферка 1 говорит что ошибка UnexpectedElementError


Даю последнюю подсказку в этой теме:
bool QXmlStreamReader::atEnd () const

"циферка 1" - говорит о том что atEnd() вернула true!


Название: Re: QTcpSocket и QXmlStreamWriter
Отправлено: Blayder от Июль 23, 2009, 09:42
Цитировать
Код
C++ (Qt)
int z=0;
 
 
  while(!rd->atEnd() || (z = rd->atEnd()))
  {
     int i = rd->atEnd();
 
 
     QMessageBox::about(0,"AAAAAAAAAAAA",QString::number(z));
Цитировать
(z = rd->atEnd())
тож самое что и
Цитировать
int i = rd->atEnd();
т.е. там может должно быть так:
Код
C++ (Qt)
while(!rd->atEnd() || (z == rd->atEnd()))


Название: Re: QTcpSocket и QXmlStreamWriter
Отправлено: max1983 от Июль 23, 2009, 11:34
Цитировать
"циферка 1" - говорит о том что atEnd() вернула true!

Все верно я ошибся принял за другой возврат ошибки.  :o

Так как QXmlStreamReader и его братан QXmlStreamWriter работают крайне странно с сокетом
они мне больше не нужны так как их практическое применение в данной связке просто не является удобным или практически правильным подходом.
Я решу свою задачу простым сокетом быстро и без проблем.
Если кто имеет пример практического использования - пусть выложит другим будет интересно.


Название: Re: QTcpSocket и QXmlStreamWriter
Отправлено: ритт от Июль 23, 2009, 12:47
слов нет


Название: Re: QTcpSocket и QXmlStreamWriter
Отправлено: pastor от Июль 23, 2009, 13:15
Я решу свою задачу простым сокетом быстро и без проблем.

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


Название: Re: QTcpSocket и QXmlStreamWriter
Отправлено: max1983 от Июль 23, 2009, 13:27
Цитировать
Чувствую ещё будет аналогичная тема, но связанная с сокетами, мол почему приходит часть данных, а не все сразу.

Уважаемый если тема и возникнет, то из за специфики QT я досихпор программировал в С++ cli .Net и проблем не было у меня ни с сокетами ни QXmlStreamWriter/Reader-ами. Имена типов схожи и функции тоже я логично предположил что и работают по одинаковому принципу
что в следствии стало ясно что эт не так. Ну и что тут такого что мне не подходят эти классы для парсинга?
Гляну Dom если не понравится то тогда просто сокетами сделаю.


Название: Re: QTcpSocket и QXmlStreamWriter
Отправлено: denka от Июль 23, 2009, 13:35
Цитировать
Чувствую ещё будет аналогичная тема, но связанная с сокетами, мол почему приходит часть данных, а не все сразу.

Уважаемый если тема и возникнет, то из за специфики QT я досихпор программировал в С++ cli .Net и проблем не было у меня ни с сокетами ни QXmlStreamWriter/Reader-ами. Имена типов схожи и функции тоже я логично предположил что и работают по одинаковому принципу
что в следствии стало ясно что эт не так. Ну и что тут такого что мне не подходят эти классы для парсинга?
Гляну Dom если не понравится то тогда просто сокетами сделаю.

Уважаемый никакой специфики нет(разве что только ваш стиль "программирования").
Знание букв не подразумевает правильность написания слов, а знание слов не подразумевает умение строить предложения. Так что лучше учите мать часть, чтоб в дальнейшем не ломать голову себе и не тратить время людей при этом оскорбляя их


Название: Re: QTcpSocket и QXmlStreamWriter
Отправлено: kuzulis от Июль 23, 2009, 13:37
2 max1983 ,

Цитировать
Гляну Dom если не понравится то тогда просто сокетами сделаю.
Дум тож не поможет.. чтобы не терять данные можно попробовать таким макаром читать: http://www.forum.crossplatform.ru/index.php?showtopic=3030&st=20

см. последний топик

т.е взять эту идею и уже применить её к своей проблеме.. хотя хз - решать Вам :)


Название: Re: QTcpSocket и QXmlStreamWriter
Отправлено: pastor от Июль 23, 2009, 13:37
Я повторюсь еще раз. Допустим ты передаешь файл размером 100Мб, на другом конце его принимаешь. Так вот, такого не будет, что файл прийдет весь целиком. Я имел ввиду это, и ничего более. И это касается как сокетов так и QXmlStreamReader-а, работающего поверх сокета. Нужна дочитка и конкатенация частей (что и требовалось при работе в твоем случае с  QXmlStreamReader)


Название: Re: QTcpSocket и QXmlStreamWriter
Отправлено: ритт от Июль 23, 2009, 15:20
не разбазаривай свой талант на Qt - ты уже сейчас можешь устроиться в мелкосовт или мозиллу! осчастливь их...