Results 1 to 18 of 18

Thread: QByteArray problem

  1. #1
    Join Date
    Jun 2008
    Posts
    33
    Thanks
    1
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Unhappy QByteArray problem

    Hi again.

    I have this problem. I have two network applications. First application write into socket QByteArray

    Qt Code:
    1. QByteArray array = new QByteArray();
    2. QDataStream stream(array, QIODevice::WriteOnly);
    3. stream.setVersion(QDataStream::Qt_4_4);
    4.  
    5. streamOut << quint32(Data::PluginData) << pluginName << quint32(ProgramViewerMenu::NewImage) << shot.toImage();
    6.  
    7. first number is 2 and second is 1.
    8.  
    9. socket->write(array);
    To copy to clipboard, switch view to plain text mode 

    In other application I read the first number

    Qt Code:
    1. QDataStream streamOut(socket);
    2. streamOut.setVersion(QDataStream::Qt_4_4);
    3.  
    4. quint32 dataType;
    5. streamOut >> dataType;
    6. qDebug() << "data thread dataType" << dataType;
    7.  
    8. QByteArray array;
    9. array = socket->readAll();
    To copy to clipboard, switch view to plain text mode 

    and than te array with remaining data give to other class of this application by signal and slot. Than I read the pluginName which is QString and it read it correctly. Than I pass the array to another class like a argument in function

    Qt Code:
    1. QDataStream streamOut(array);
    2. streamOut.setVersion(QDataStream::Qt_4_4);
    3.  
    4. QString name;
    5. streamOut >> name;
    6.  
    7. menu->readData(array);
    To copy to clipboard, switch view to plain text mode 

    In that class I want to read the second number

    Qt Code:
    1. QDataStream stream(array);
    2. stream.setVersion(QDataStream::Qt_4_4);
    3.  
    4. quint32 data;
    5. stream >> data;
    To copy to clipboard, switch view to plain text mode 

    But this number is not 1 like I wrote but 28 and I dont know why. When I read all data in one class without passing it, it reads it corretly.
    So is there any other way how to write to and read from QByteArray? Or do I have to do something to prepare data for passing to another class?
    Thank you.

  2. #2
    Join Date
    Dec 2006
    Posts
    849
    Thanks
    6
    Thanked 163 Times in 151 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: QByteArray problem

    Note that readAll reads the available data. You have to make sure that all the data you sent (at least for this package) has arrived. Usually this is done by sending the package size first. Examples somewhere in the Qt docs.

    Also note that each time you construct a QDataStream on your QByteArray, the "file pointer" points to the beginning of the QByteArray. The second stream does not know or care what has been read in the first stream.

    Solutions:
    * you can also read (with QDataStream) directly from the socket. No need to read into a QByteArray. Pass the socket and read from it directly.
    * pass a common QDataStream

    HTH

  3. #3
    Join Date
    Sep 2008
    Posts
    60
    Thanks
    8
    Thanked 10 Times in 9 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QByteArray problem

    I think when you pass an array to menu->readData(array), the first data item in the array is your string. My guess is you need to pass streamOut instead of the array: the stream will be positioned on a correct number that follows the string that you've just read.

  4. #4
    Join Date
    Jun 2008
    Posts
    33
    Thanks
    1
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QByteArray problem

    Thanks guys.
    But I cant pass QDataStream because this error:
    initializing argument 1 of `void DataThread:luginData(QDataStream)'
    d:/Programy/QT_4.4.1/include/QtCore/../../src/corelib/io/qdatastream.h `QDataStream::QDataStream(const QDataStream&)' is private

    And about passing socket. Application writes quite quickly to this socket and I dont know whether it is a good idea.

    Is there any other way how to use QByteArray and tell stream where to read from?

  5. #5
    Join Date
    Sep 2008
    Posts
    60
    Thanks
    8
    Thanked 10 Times in 9 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QByteArray problem

    It looks like you are passing QDataStream by value. Try passing by pointer or by reference.

  6. #6
    Join Date
    Jun 2008
    Posts
    33
    Thanks
    1
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QByteArray problem

    Yes you were right. When I pass QDataStream like pointer error disappeared. But it didnt solve the problem. It didnt read 1 and not even 28 but 0.
    Any idea whats wrong?

  7. #7
    Join Date
    Dec 2006
    Posts
    849
    Thanks
    6
    Thanked 163 Times in 151 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: QByteArray problem

    let's trade: code for help?

  8. #8
    Join Date
    Jun 2008
    Posts
    33
    Thanks
    1
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QByteArray problem

    Of course sorry:

    I didnt change writing to the slot only reading from it.

    Qt Code:
    1. QByteArray array;
    2. array = socket->readAll();
    3. QDataStream *streamOut = new QDataStream(array);
    4. streamOut->setVersion(QDataStream::Qt_4_4);
    5.  
    6. quint32 dataType;
    7. *streamOut >> dataType;
    8. qDebug() << "data thread dataType" << dataType;
    9.  
    10. if (dataType == Data::PluginData)
    11. emit pluginDataIn(streamOut);
    12. ...
    13. connect(connection, SIGNAL(pluginDataIn(QDataStream*)), plugins, SLOT(dataIn(QDataStream*)));
    14. ...
    To copy to clipboard, switch view to plain text mode 

    Qt Code:
    1. void Plugins::dataIn(QDataStream* streamOut)
    2. {
    3. QString name;
    4. *streamOut >> name;
    5.  
    6. qDebug() << name;
    7.  
    8. quint32 type;
    9. *streamOut >> type;
    10.  
    11. qDebug() << type;
    12.  
    13. Menu *menu = menus.value(name);
    14. if(!menu)
    15. {
    16. qDebug() << "return menu";
    17. return;
    18. }
    19. menu->readData(streamOut);
    To copy to clipboard, switch view to plain text mode 

    Qt Code:
    1. void ProgramViewerMenu::readData(QDataStream* stream)
    2. {
    3. if (!isListening)
    4. return;
    5.  
    6. window->getData(stream);
    7. showWindow();
    8. }
    9.  
    10. void ViewerWindow::getData(QDataStream* streamOut)
    11. {
    12. quint32 data;
    13. *streamOut >> data;
    14.  
    15. qDebug() << "viewer window data" << quint32(data);
    16.  
    17. switch (data)
    18. {
    19. case ViewerWindow::NewImage :
    20. setImage(streamOut);
    21. break;
    22. case ViewerWindow::Pixels :
    23. setPixels(streamOut);
    24. break;
    25. case ViewerWindow::Stop :
    26. clearImage();
    27. emit closing();
    28. break;
    29. }
    To copy to clipboard, switch view to plain text mode 

    I hope it helps.
    But I will be pleased if it could be do in other way than passing QDataStream*. Maybe somehow use QByteArray or another class I dont know.

  9. #9
    Join Date
    Dec 2006
    Posts
    849
    Thanks
    6
    Thanked 163 Times in 151 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: QByteArray problem

    a) Did you check that your readAll() really did read all the data you sent? (It reads the available data. It is not guaranteed that all you sent is available at once and/or in a single read!). You do need to fix that!
    Calling readAll the way you do is not correct: see the fortune client example in the Qt docs:network-fortuneclient-client-cpp The function readClient() 'waits' with processing a message til the complete block has been read. The server sends -as said earlier- the size of the block as the first quint32 of each block.
    (Make sure by printing the size of the amount of bytes read.)

    b) why don't you wrap the socket in a QDataStream directly, rather than reading into a QByteArray and wrapping that?

    Other than esp. a) your code looks basically correct (it is not complete, so obviously there might be hidden issues).
    At what point does your code fail (which >> does not read the expected value)?

    HTH

  10. #10
    Join Date
    Sep 2008
    Posts
    60
    Thanks
    8
    Thanked 10 Times in 9 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QByteArray problem

    I also noticed that you write quint32, QString, quint32 and then shot.toImage().

    Qt Code:
    1. streamOut << quint32(Data::PluginData) << pluginName << quint32(ProgramViewerMenu::NewImage) << shot.toImage();
    To copy to clipboard, switch view to plain text mode 

    But when you read, you read quint32, QString, quint32 and quint32.

    Does shot.toImage() returns quint32?

  11. #11
    Join Date
    Jun 2008
    Posts
    33
    Thanks
    1
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QByteArray problem

    to yuriry: sorry that was my mistake. It should be:

    Qt Code:
    1. void Plugins::dataIn(QDataStream* streamOut)
    2. {
    3. QString name;
    4. *streamOut >> name;
    5.  
    6. qDebug() << name;
    7.  
    8. /* quint32 type;
    9. *streamOut >> type;
    10.  
    11. qDebug() << type;*/
    12.  
    13. Menu *menu = menus.value(name);
    14. if(!menu)
    15. {
    16. qDebug() << "return menu";
    17. return;
    18. }
    19. menu->readData(streamOut);
    20. }
    To copy to clipboard, switch view to plain text mode 

    It should read quint32, QString, quint32 and QImage. shot is a QPixmap and returning QImage.
    I tried to read second quint32 in Plugins::dataIn and it works, quint32 was read correctly, but when I comment this part of code like here and call menu->readData(streamOut); it was read incorrectly in ViewerWindow::getData and I do not know why becouse I only pass the QDataStream* or QByteArray which I tried to pass before.

    to caduel: I know I should write size of block first and I will repaire it.
    But I know that all data which I write is read because when I read it in one class it read all data corretly but when I pass QDataStream* or QByteArray to another class, in this case from class Plugins to class ProgramViewerMenu and than ViewerWindow, it doesnt read it correctly.

    I was wondering if isnt problem that classes ProgramViewerMenu and ViewerWindow are in plugin, in dll file which is loaded when program starts.

    And it doesnt work even if I wrap the socket in QDataStream directly i ve just tried it.

  12. #12
    Join Date
    Sep 2008
    Posts
    60
    Thanks
    8
    Thanked 10 Times in 9 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QByteArray problem

    Could the problem occur because QByteArray is on the stack and QDataStream is on the heap:

    Qt Code:
    1. QByteArray array;
    2. array = socket->readAll();
    3. QDataStream *streamOut = new QDataStream(array);
    To copy to clipboard, switch view to plain text mode 

    I was wondering that may be when you emit a signal the slot is not called right away but somehow delayed and executed through event mechanism. Then ByteArray goes out of scope and the data that QDataStream refers to become invalid. This is a just a guess, but I would also try this code to double check:

    Qt Code:
    1. QByteArray* array = new QByteArray();
    2. *array = socket->readAll();
    3. QDataStream *streamOut = new QDataStream(array);
    To copy to clipboard, switch view to plain text mode 

  13. #13
    Join Date
    Jun 2008
    Posts
    33
    Thanks
    1
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QByteArray problem

    No it didnt work. Any other Ideas?

  14. #14
    Join Date
    Sep 2008
    Posts
    60
    Thanks
    8
    Thanked 10 Times in 9 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QByteArray problem

    Yeah, I read up on signals - my suggestion was useless because you use a direct connection and all signals emitted on such connections are executed without any delay. In addition, QByteArray is implicitly shared...

    I do not see anything obvious to suggest. May be only trying this code:

    Qt Code:
    1. QDataStream *streamOut = new QDataStream(socket->readAll());
    To copy to clipboard, switch view to plain text mode 

    But it'll probably change nothing.

  15. #15
    Join Date
    Jun 2008
    Posts
    33
    Thanks
    1
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QByteArray problem

    Well I ve tried to read directly from socket and pass QTcpSocket* and it works. But it doesnt work correctly.
    I think its becouse I write to socket very quickly and also I havent added that data size control yet. But still I do not think that it is a good idea to pass socket.
    If think there could be problem if i write some data before all data which was written first are read. Am I wrong?
    And can me somebody explain why it works with QTcpSocket and doesnt with QByteArray?

  16. #16
    Join Date
    Sep 2008
    Posts
    60
    Thanks
    8
    Thanked 10 Times in 9 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QByteArray problem

    As Caduel pointed out readAll() might not had read all the data that you sent, only the data currently available on the socket.

    QByteArray QIODevice::readAll ()

    Reads all available data from the device, and returns it as a QByteArray.

    This function has no way of reporting errors; returning an empty QByteArray() can mean either that no data was currently available for reading, or that an error occurred.
    Try putting a sleep before reading the data from the socket and check readBufferSize() (if it is not 0 then call setReadBufferSize(0) to make it unlimited).

  17. #17
    Join Date
    Jun 2008
    Posts
    33
    Thanks
    1
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QByteArray problem

    So I cant use QByteArray in any way? And why? I still do not understant why it works with QTcpSocket and doesnt with QByteArray

    And can me somebody show some piece of code how to correctly write to socket and read from socket? In my case I think I write to socket faster than it could be read from it. Is it possible? And how to do it right?

    Thanks to all.

  18. #18
    Join Date
    Sep 2008
    Posts
    60
    Thanks
    8
    Thanked 10 Times in 9 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QByteArray problem

    Take a look at void Server::sendFortune() as a write example and void Client::readFortune() as a read example.

Similar Threads

  1. Weird problem: multithread QT app kills my linux
    By Ishark in forum Qt Programming
    Replies: 2
    Last Post: 8th August 2008, 09:12
  2. Steps in solving a programming problem?
    By triperzonak in forum General Programming
    Replies: 8
    Last Post: 5th August 2008, 08:47
  3. External Lib read from QBuffer on Calback problem
    By patrik08 in forum Qt Programming
    Replies: 2
    Last Post: 2nd June 2008, 19:43
  4. QByteArray with network data
    By merlvingian in forum Qt Programming
    Replies: 1
    Last Post: 1st June 2007, 17:53
  5. Replies: 16
    Last Post: 7th March 2006, 15:57

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.