Results 1 to 12 of 12

Thread: QByteArray revisited

  1. #1
    Join Date
    Jan 2008
    Posts
    107
    Thanks
    36
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Question QByteArray revisited

    Hi,

    I'm having problems extracting contents from a QByteArray...

    Given the code:
    Qt Code:
    1. QByteArray unitData;
    2. unitData=tcpSocket.readAll(); // incoming binary data
    3. .
    4. .
    5. .
    6. const char *c_str = unitData.toHex().data();
    7. cout << "Received: " << c_str << endl;
    To copy to clipboard, switch view to plain text mode 

    outputs correctly:
    000F353334...yacka yacka...
    but when one tries:
    Qt Code:
    1. void myUnit::checkImei (QByteArray &data)
    2. {
    3. bool ok;
    4. // check the # of bytes in the header
    5. unsigned int nbrBytes = data.left(2).toUInt(&ok,16);
    6. if (!ok) cout << "Conversion impossible!" << endl;
    7. cout << "# bytes: " << nbrBytes << endl;
    8.  
    9. }
    To copy to clipboard, switch view to plain text mode 

    number of bytes is *always* zero!

    Any pointers would be highly appreciated...
    Kind regards,
    Pedro Doria Meunier
    Last edited by jpn; 15th January 2008 at 12:21. Reason: reformatted to look better

  2. #2
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    5,372
    Thanks
    28
    Thanked 976 Times in 912 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QByteArray revisited

    Quote Originally Posted by pdoria View Post
    const char *c_str = unitData.toHex().data();
    cout << "Received: " << c_str << endl;

    outputs correctly:
    000F353334...yacka yacka...
    It's a pure accident.

    Use: cout << "Received: " << unitData.toHex().data() << endl;
    or:
    Qt Code:
    1. QByteArray hex = unitData.toHex();
    2. cout << "Received: " << hex.data() << endl;
    To copy to clipboard, switch view to plain text mode 

    Have you tried printing contents of data.left(2).toHex() in checkImei()?

  3. #3
    Join Date
    Jan 2008
    Posts
    107
    Thanks
    36
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: QByteArray revisited

    Thanks for replying.

    Yes I did. As expected it returned '000F' (the header for the the number of bytes following...)

    What I really want is to convert those two bytes into integer...

    Kind regards,
    Pedro Doria Meunier

  4. #4
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    5,372
    Thanks
    28
    Thanked 976 Times in 912 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QByteArray revisited

    It seems that QByteArray expects digits, not binary data:
    Qt Code:
    1. #include <QCoreApplication>
    2. #include <QByteArray>
    3.  
    4. #include <QtDebug>
    5.  
    6. int main( int argc, char ** argv )
    7. {
    8. QCoreApplication app( argc, argv );
    9.  
    10. QByteArray b( QByteArray::fromHex("000F") );
    11.  
    12. bool ok1, ok2;
    13. qDebug() << b.toHex();
    14. qDebug() << b.toUInt( &ok1, 16 );
    15. qDebug() << ok1;
    16. qDebug() << b.toHex().toUInt( &ok2, 16 );
    17. qDebug() << ok2;
    18.  
    19. return 0;
    20. }
    To copy to clipboard, switch view to plain text mode 

    Output:
    $ ./ba
    "000f"
    0
    false
    15
    true

  5. The following user says thank you to jacek for this useful post:

    pdoria (15th January 2008)

  6. #5
    Join Date
    Jan 2008
    Posts
    107
    Thanks
    36
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: QByteArray revisited

    I'm still struggling to get anything useful from a QByteArray that has received binary data...

    The most frustrating thing is, per debugging, seeing that the data is there and one can't ever do something of myBA.left(2).toUInt() ...

    The toHex() function extracts it correctly, though...
    something like: 000F313233343536373839303132333435
    A 000F header, followed by the actual data...

    Size also reports correctly: 17 bytes.

    QString objects don't work for me either since their data stops at a \0, of which the expected incoming data is abundant of.... (actually most of the headers begin with 00-something...)

    I *really* could use the help of you gurus out there on this one, since this is actually diverting me from the true implementation of the software...

    Thanks in advance,
    Pedro Doria Meunier.

  7. #6
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    5,372
    Thanks
    28
    Thanked 976 Times in 912 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QByteArray revisited

    Have you tried QDataStream?

  8. #7
    Join Date
    Jan 2008
    Posts
    107
    Thanks
    36
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Post Re: QByteArray revisited

    Jacek,

    Thanks for the suggestion.

    But I wonder...
    Why the need to use this when QTcpSocket::readAll does the job?
    Furthermore... why can't one extract binary data (using one the **appealing* methods) directly from a QByteArray? Doesn't it feel like BS?

    readAll is a very convenient method and it *works*. the problem resides in QByteArray (at least from my newbie point of view )

    So, as far as I'm concerned this is still an open question that, for the life of me, I can't seem to overcome...

    Kind regards,
    Pedro Doria Meunier.

  9. #8
    Join Date
    Jan 2008
    Posts
    107
    Thanks
    36
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Unhappy Re: QByteArray revisited

    bump:

    Still stuck. Could someone please provide a good example on how to overcome this?

    Thanks in advance,
    Pedro Doria Meunier.

  10. #9
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    5,372
    Thanks
    28
    Thanked 976 Times in 912 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QByteArray revisited

    Quote Originally Posted by pdoria View Post
    Why the need to use this when QTcpSocket::readAll does the job?
    Because readAll() does a different part of the job. QDataStream knows how to extract an uint from a byte array.
    Qt Code:
    1. QDataStream ds( ... );
    2. ds.setByteOrder( ... );
    3. quint16 i;
    4. ds >> i;
    To copy to clipboard, switch view to plain text mode 

  11. The following user says thank you to jacek for this useful post:

    pdoria (17th January 2008)

  12. #10
    Join Date
    Jan 2008
    Posts
    107
    Thanks
    36
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Question Re: QByteArray revisited -- binary data (16 bits)

    Ok.
    Thanks for the reply. QDataStream put out a lot of segfaults outputing to a qint16 data[nbrBytes] ... and I'm really not sure this is the way to go (see below)

    Let's start over to see if I can make any sense of this...

    I have a device that sends binary data -- 16bit values -- it sends this data all at once.

    I'm giving out my code so that someone can help me here...

    myunit.h

    Qt Code:
    1. #ifndef CONNTHREAD_H
    2. #define CONNTHREAD_H
    3.  
    4. #include <QThread>
    5. #include <QTcpSocket>
    6. #include <server.h>
    7.  
    8. class myUnit : public QThread
    9. {
    10. Q_OBJECT
    11.  
    12. public:
    13. QTcpSocket tcpSocket;
    14. myUnit ( int socketDescriptor, Server *parent );
    15. ~myUnit ();
    16. void run ();
    17. void checkImei (QByteArray &bData);
    18.  
    19. char * peerAddress; // Unit's IP
    20. char imei[15]; // unique unit identifier (IMEI)
    21. bool gotImei; // semaphore for determining whether we have the unit's IMEI or not
    22.  
    23. //SNIP sensitive objects
    24.  
    25. signals:
    26. void error ( QTcpSocket::SocketError socketError );
    27.  
    28. public slots:
    29. void disconnected ();
    30. void incomingData ();
    31. quint64 writeData ();
    32.  
    33. private:
    34. int socketDescriptor;
    35. protected:
    36. Server *server;
    37. };
    38. #endif
    To copy to clipboard, switch view to plain text mode 

    myunit.cpp

    Qt Code:
    1. #include "myunit.h"
    2. #include <iostream>
    3. #include <QtNetwork>
    4. #include <QDebug> // TODO remove in production!
    5.  
    6. using namespace std;
    7.  
    8. extern QString getDateTime();
    9. extern char * toCharP ( QString str );
    10.  
    11. myUnit::myUnit ( int socketDescriptor, Server *parent ) : QThread ( parent )
    12. {
    13. // initialize the unit's socket --> provided by Server::incomingConnection()
    14. if ( !tcpSocket.setSocketDescriptor ( socketDescriptor ) )
    15. {
    16. emit error ( tcpSocket.error() );
    17. return;
    18. }
    19. // this unit doesn't have an IMEI yet...
    20. gotImei=false;
    21. // initialize our imei (000000000000000)
    22. strcpy(imei, "00000000000000");
    23. // access to this parent server object
    24. server=parent;
    25. connect ( &tcpSocket, SIGNAL ( readyRead() ), this, SLOT ( incomingData() ) );
    26. connect ( &tcpSocket, SIGNAL ( disconnected() ), this, SLOT ( disconnected() ) );
    27. }
    28.  
    29.  
    30. /**
    31.  * myUnit::~myUnit()
    32.  * Reimplementation of the QThread's destructor.
    33.  * Just to exhibit a message upon this client disconnection.
    34.  */
    35. myUnit::~myUnit()
    36. {
    37. char * dt = toCharP ( getDateTime() );
    38. cout << dt << ": Unit [" << imei << "] disconnected." << " # active clients: " << server->nbrClients << endl;
    39. }
    40.  
    41. /**
    42.  * void myUnit::run()
    43.  * Reimplementation of QThread::run().
    44.  * Just to exhibit a message upon a new client connection.
    45.  * The exec() begins a loop for the thread's events.
    46.  */
    47. void myUnit::run()
    48. {
    49. char * dt = toCharP ( getDateTime() );
    50. peerAddress = toCharP ( tcpSocket.peerAddress().toString() );
    51. cout << dt << ": Incoming connection from [" << peerAddress << "]" << " # clients: " << server->nbrClients << endl;
    52.  
    53. exec();
    54. }
    55.  
    56. /**
    57.  * void myUnit::disconnected ();
    58.  * This function (slot) is connected to the tcpSocket disconnected() signal.
    59.  * Decrements the parent server object nbrClients member and exits the thread.
    60.  * The quit() insures a graceful exit from the thread, cleaning up child objects and associated memory.
    61.  */
    62. void myUnit::disconnected()
    63. {
    64. server->nbrClients--;
    65. this->quit();
    66. }
    67.  
    68. /**
    69.  * void myUnit::incomingData ();
    70.  * This function (slot) is connected to the tcpSocket readyRead() signal, so that when any data is available
    71.  * on the socket it's thrown here.
    72.  * returns the number of bytes read.
    73.  */
    74. void myUnit::incomingData ()
    75. {
    76.  
    77. QByteArray unitData;
    78. unitData=tcpSocket.readAll();
    79. int nbrBytes = unitData.length();
    80. cout << "Incoming data from [" << peerAddress << "] - Nbr. of bytes: " << nbrBytes;
    81. if (!gotImei) {
    82. cout << " - checking IMEI..." << endl;
    83. checkImei(unitData);
    84. }
    85. else {
    86. cout << " - parsing data..." << endl;
    87. }
    88. }
    89.  
    90. quint64 myUnit::writeData ()
    91. {
    92. // TODO
    93. return 0;
    94. }
    95.  
    96. void myUnit::checkImei (QByteArray &bData)
    97. {
    98. QString sData(bData);
    99. unsigned int nBytes = sData.left(2).toUInt();
    100. cout << "nBytes: " << nBytes << endl;
    101. cout << "sData: " << sData.right(15).toAscii().data() << endl;
    102. }
    To copy to clipboard, switch view to plain text mode 

    As you can see I'm even converting the QByteArray into a QString in checkImei...
    Only if I assign sData=bData.right(15).toAscii().data() right off will I get the Imei... I'm aware that this is expected behavior since QString data is \0 terminated and the first 2 bytes of dData contain a \0 byte value.

    So I wonder... If my devices output everything in binary,16bit values, how do I write a function to extract the data coming in that socket?! :frustrated:

    Please help using the above code so that I can get out of this and start focusing on the real implementation...
    (I really don't want to go back to PHP...)

    Thanks in advance,
    Pedro Doria Meunier.
    Last edited by pdoria; 17th January 2008 at 05:44.

  13. #11
    Join Date
    Jan 2008
    Posts
    107
    Thanks
    36
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Unhappy Re: QByteArray revisited

    bump.

    Anyone?

    I've tried QDataStream and QTextStream ... this is getting insane.
    It shouldn't be THIS hard to extract bytes from a bloody socket stream!
    Please help.

    Thank you.

  14. #12
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    5,372
    Thanks
    28
    Thanked 976 Times in 912 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QByteArray revisited -- binary data (16 bits)

    First of all you have to create the socket in run() (without a parent) and you should use direct connections (instead of the default automatic ones) between the socket and the thread object. That's because the thread object lives in the GUI thread and you want to use your socket in a separate thread that will be created when you invoke start().

    I don't see QDataStream anywhere in above snippet, so I can't say for sure why it causes segfaults, but most likely it has something to do with thread affinity.
    Last edited by jacek; 17th January 2008 at 18:31. Reason: typo

Similar Threads

  1. QByteArray format
    By nowire75 in forum Newbie
    Replies: 1
    Last Post: 13th July 2007, 09:53
  2. QByteArray with network data
    By merlvingian in forum Qt Programming
    Replies: 1
    Last Post: 1st June 2007, 17:53
  3. QDomElement to QByteArray ?
    By probine in forum Qt Programming
    Replies: 3
    Last Post: 2nd May 2006, 17:01
  4. Reading QByteArray from QDataStream Qt3.3
    By high_flyer in forum Qt Programming
    Replies: 2
    Last Post: 1st April 2006, 20:23
  5. How to read a Number from the QByteArray
    By antonio.r.tome in forum Qt Programming
    Replies: 2
    Last Post: 24th February 2006, 15:24

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.