Results 1 to 6 of 6

Thread: Issue using QTcpSocket - works for QString but not for QImage

  1. #1
    Join Date
    Jul 2009
    Location
    London
    Posts
    9
    Thanks
    2
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Issue using QTcpSocket - works for QString but not for QImage

    Hi,

    I have written a server/client, initially using the Fortune examples. The data received is a QVariant - so the QVariant type can be used to determine what to do with the data.

    Apologies if my explanations are not great - I am not great with describing what I want to do/have done in programming-speak.

    For e.g. a QString it works fine (I guess as it comes in one block?). however attempting with a QImage -> the version/description/data type are sent OK --> If I output the emit_message in read_client then it outputs these OK. I assume this is because the images are larger and need to be sent in multiple blocks. Hence I believe the readClient() would be called multiple times for the same serialized data item. I can't work out how to deal with this gracefully - should I create some function to deal with whether this is a fresh readClient() or one to deal with data that is mid-transmission?
    Either that, or I need some sort of loop based on data/the size sent in the header, to build up "data" from the blocks/packets received but am unsure of how to go about doing this. I also send an end of data flag - could this also be used? I have looked through the forums - there are multiple issues on this topic, but I could not find a specific answer (well not with the search terms I have been using)...

    Any help would be much appreciated (as well as any pointers if my code is poor -> I am a bit of a QT noob)..

    Here is a stripped down version of the codes.

    Server:
    Qt Code:
    1. void Server::incomingConnection(int socketId) {
    2. ServerSocket *socket = new ServerSocket(this);
    3. socket->setSocketDescriptor(socketId);
    4. }
    5.  
    6.  
    7. ServerSocket::ServerSocket(QObject *parent) : QTcpSocket(parent)
    8. {
    9. connect(this, SIGNAL(readyRead()), this, SLOT(readClient()));
    10. connect(this, SIGNAL(disconnected()), this, SLOT(deleteLater()));
    11. blockSize = 0;
    12. }
    13.  
    14. void ServerSocket::readClient()
    15. {
    16. QDataStream in(this);
    17. in.setVersion(QDataStream::Qt_4_5);
    18. if (blockSize == 0) {
    19. if (bytesAvailable() < (sizeof(quint16)))
    20. return;
    21. in >> blockSize;
    22. }
    23. if (bytesAvailable() < (quint16)(blockSize + sizeof(quint16) + sizeof(quint8)))
    24. return;
    25. quint8 version;
    26. QString description;
    27. QVariant data;
    28. quint16 endFlag;
    29. in >> version;
    30. in >> description;
    31. in >> data;
    32. in >> endFlag;
    33.  
    34. QString emit_message = "\n\tVersion: " + QString::number(version) +
    35. "\n\tType(" + QString(data.typeName()) + "): " + QString::number(data.type()) +
    36. "\n\tSize: " + QString::number(blockSize) +
    37. "\n\tMessage: " + description +
    38. "\n\tData: " + data.toString() +
    39. "\n\tEndFlag: " + QString::number(endFlag);
    40.  
    41. }
    To copy to clipboard, switch view to plain text mode 


    client:
    Qt Code:
    1. //this is fired on the click of a QPushButton
    2. void Client::sendRequest()
    3. {
    4. QTcpSocket socket;
    5. socket.connectToHost(serverName, serverPort);
    6.  
    7. if (!socket.waitForConnected(TIMEOUT)) {
    8. emit error(socket.error(), socket.errorString());
    9. return;
    10. }
    11.  
    12. QVariant data;
    13. QString description;
    14. //text is set in a QLineEdit
    15. if (text == "image") {
    16. data = QImage("someimage.jpg");
    17. description = "This is an image";
    18. }
    19. else {
    20. data = text;
    21. description = "This is some text";
    22. }
    23.  
    24. QByteArray block;
    25. QDataStream out(&block, QIODevice::WriteOnly);
    26. out.setVersion(QDataStream::Qt_4_5);
    27. out << quint16(0) << quint8(1) << description << data << quint16(0xFFFF);
    28. out.device()->seek(0);
    29. out << (quint16)(block.size() - sizeof(quint16) - sizeof(quint8) - sizeof(quint16));
    30. socket.write(block);
    31. socket.flush();
    32. qDebug() << "Sending: [" + description + data.toString()
    33. + "] to server(" + serverName + ":" + QString::number(serverPort) + ")";
    34. }
    To copy to clipboard, switch view to plain text mode 

    Thanks,

    James

  2. #2
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Issue using QTcpSocket - works for QString but not for QImage

    What do you send as the block size?
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  3. #3
    Join Date
    Jul 2009
    Location
    London
    Posts
    9
    Thanks
    2
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Issue using QTcpSocket - works for QString but not for QImage

    Hi Wysota,

    Is it not (line 27 of the client code):
    Qt Code:
    1. out << (quint16)(block.size() - sizeof(quint16) - sizeof(quint8) - sizeof(quint16));
    To copy to clipboard, switch view to plain text mode 
    ?

    Which is the size of everything minus itself(quint16), the version(quint8) and the endFlag(quint16). I have tried casting it to a quint64 and 32 instead but this makes no difference. Although that was a few days ago so i will try this again now.

    Thanks,

    James

  4. #4
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Issue using QTcpSocket - works for QString but not for QImage

    What is "everything"? blocksize determines how much data needs to be available before the reading function tries to read the next request from the stream. Furthermore you are doing some complicated operations regarding filling the data stream with proper information, writing some 0, then some 1 and then trying to overwrite them with something else (the block size, I guess).
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  5. #5
    Join Date
    Jul 2009
    Location
    London
    Posts
    9
    Thanks
    2
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Issue using QTcpSocket - works for QString but not for QImage

    OK I have got it - basically the client was disconnecting the socket right after it had written everything so the server was getting a mangled message.

    I added:

    Qt Code:
    1. socket.waitForDisconnected(5000);
    To copy to clipboard, switch view to plain text mode 

    Is there a better way to get the client to wait until the data has been read?

    I also had to move all the server variables outside the slot attached to the readyRead function as the datastream and other variables were being re-created each time the function was called.

    As an aside - is my method of using a QVariant bad practice ? I would assume that it is time consuming to cast each type into and out of a QVariant with a heavy load. Would it be better to use separate sockets for the different types?

    Here is the end code:

    Server:

    Qt Code:
    1. ServerSocket::ServerSocket(QObject *parent) : QTcpSocket(parent)
    2. {
    3. connect(this, SIGNAL(readyRead()), this, SLOT(readClient()));
    4. connect(this, SIGNAL(disconnected()), this, SLOT(deleteLater()));
    5. blockSize_8 = 0;
    6. blockSize_16 = 0;
    7. blockSize_32 = 0;
    8. blockSize_64 = 0;
    9. version = 0;
    10. data = 0;
    11. description = QString();
    12. endFlag = 0x0;
    13. in.setDevice(this);
    14. in.setVersion(QDataStream::Qt_4_5);
    15. }
    16.  
    17. ServerSocket::~ServerSocket()
    18. {
    19. in.unsetDevice();
    20. }
    21.  
    22. void ServerSocket::ServerSocket()
    23. {
    24. if (blockSize_64 == 0) {
    25. if (bytesAvailable() < (sizeof(quint64) + sizeof(quint8)))
    26. return;
    27. in >> blockSize_64;
    28. in >> version;
    29. }
    30.  
    31. if (bytesAvailable() < (quint64)(blockSize_64 + sizeof(quint16)))
    32. return;
    33. in >> description;
    34. in >> data;
    35. in >> endFlag;
    36.  
    37. QString emit_message = "\n\tVersion: " + QString::number(version) +
    38. "\n\tType(" + QString(data.typeName()) + "): " + QString::number(data.type()) +
    39. "\n\tSize: " + QString::number(blockSize_64) +
    40. "\n\tMessage: " + description +
    41. "\n\tData: " + data.toString() +
    42. "\n\tEndFlag: " + QString::number(endFlag);
    43. QLabel * label;
    44. switch (data.type()) {
    45. //just for testing the image gets there OK
    46. case QVariant::Image:
    47. label = new QLabel();
    48. label->setPixmap(QPixmap::fromImage(data.value<QImage>()));
    49. label->show();
    50. break;
    51. case QVariant::String:
    52. break;
    53. default:
    54. break;
    55. }
    56. emit message(emit_message, Server::DATA);
    To copy to clipboard, switch view to plain text mode 


    Client:
    Qt Code:
    1. void Client::sendRequest()
    2. {
    3. QTcpSocket socket;
    4. socket.connectToHost(serverName, serverPort);
    5.  
    6. if (!socket.waitForConnected(TIMEOUT)) {
    7. emit error(socket.error(), socket.errorString());
    8. return;
    9. }
    10.  
    11. QVariant data;
    12. QString description;
    13. if (text == "image") {
    14. data = QImage("someimage.jpg");
    15. description = "This is an image";
    16. }
    17. else {
    18. data = text;
    19. description = "This is some text";
    20. }
    21. QByteArray block;
    22. QDataStream out(&block, QIODevice::WriteOnly);
    23. out.setVersion(QDataStream::Qt_4_5);
    24. //block size << version number << description.
    25. out << quint64(0) << quint8(1) << description;
    26. //data << end flag
    27. out << data << quint16(0xFFFF);
    28. out.device()->seek(0);
    29. //block size is description + data
    30. out << quint64(block.size() - sizeof(quint64) - sizeof(quint8) - sizeof(quint16));
    31. socket.write(block);
    32. socket.flush();
    33. qDebug() << "Sending: [" + description + QVariant(text).toString()
    34. + "] to server(" + serverName + ":" + QString::number(serverPort) + ")";
    35. QString emit_message = "\n\tVersion: " + QString::number(quint8(1)) +
    36. "\n\tType(" + QString(data.typeName()) + "): " + QString::number(data.type()) +
    37. "\n\tSize: " + QString::number(quint64(block.size() - sizeof(quint16) - sizeof(quint8) - sizeof(quint16))) +
    38. "\n\tMessage: " + description +
    39. "\n\tData: " + data.toString() +
    40. "\n\tEndFlag: " + QString::number(quint16(0xFFFF));
    41. qDebug() << emit_message;
    42. socket.waitForDisconnected(5000);
    43. socket.disconnectFromHost();
    44. }
    To copy to clipboard, switch view to plain text mode 

    Sorry I didn't mean to PM you..

    I just saw your reply:

    the initial quint16(0) is for the block size. The quint8(1) is the version number - this won't be hard coded in the end but is there for the possibility of backwards compatibility in the future.

    However it seems to be working now..

    Thanks for your input.

    If you have any further pointers for this they would be greatly appreciated!

  6. #6
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Issue using QTcpSocket - works for QString but not for QImage

    Unfortunately the fortune cookie example is one of the worst in Qt. I suggest you don't follow it but instead apply all the principles of network programming.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  7. The following user says thank you to wysota for this useful post:

    jamo_ (15th May 2011)

Similar Threads

  1. how to use qtcpsocket send qimage data
    By tsuibin in forum Qt Programming
    Replies: 2
    Last Post: 18th April 2012, 15:51
  2. QTcpSocket only works local
    By BrainStorm in forum Qt Programming
    Replies: 21
    Last Post: 4th June 2011, 17:49
  3. QImage to QString
    By navi1084 in forum Qt Programming
    Replies: 2
    Last Post: 7th October 2008, 08:29
  4. QImage Format Issue
    By vishal.chauhan in forum Qt Programming
    Replies: 7
    Last Post: 9th March 2007, 11:14
  5. QImage Issue
    By vishal.chauhan in forum Qt Programming
    Replies: 5
    Last Post: 5th February 2007, 05:29

Tags for this Thread

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.