QTcpSocket: how to read numbers



  • Dear all.
    It may look a very simple question, but I couldn't find any help in the qt documentation or in the web.
    All I want is to read a series of numbers (integers, double or whatever) from a TCP socket. Not strings.
    The TCP server is made in MatLab and it sends a series of numbers in double precision format (8 bytes).
    I used the readAll function to get the data and I got a QByteArray of N*8 elements (where N is the number of elements of the double array in MatLab).
    I can easily separate the N elements with the mid function, but after that how can I get the numbers from the 8-elements QByteArray object? If for example is write

    QByteArray myData;
    QByteArray myData_element;
    
    myData = socket->readAll(); //This one has N*8 elements
    myData_element = myData.mid(0,8); // This one has 8 elements
    
    qDebug() << myData_element.data();
    

    what I get is a series of strange characters.
    If the server sends one uint8 number, with

    qDebug() << myData_element.data();
    

    I get instead the acsii character relative to the number that is sent.
    I tried and tried but I can't obtain the number sent by the server (even the uint8).
    Actually, the fact that the TCP server is made in MatLab is not relevant. It may be made even in c++, but the I have the same issue if such server sends numbers in any format that is not a string.
    Do you have any suggestions?

    Thank you.


  • Qt Champions 2017

    Hi
    When you send binary data over the socket you will see the actual internal format.
    Hence you must convert it back to the real type.
    did you try
    bool ok;
    int data = myData_element.toInt(&ok,10);
    QByteArray contains many function to convert the buffer to real types. int/double etc.



  • @mrjj Yes, I tried. But the conversion fails (ok=false).
    If the server sends the number 65 (uint8) and I write the code

    bool ok;
    int number = myData_element.toInt(&ok,10);
    qDebug() << myData_element << myData_element.data() << number << ok;
    

    it will return:
    "A" A 0 false

    This is because the number 65 is related to the ascii character "A" and the toInt function will try to convert the character "A" to a number (and it will obviously fail).

    If instead it sends a double, single, int32, etc. it will display other characters and it will try to convert those characters to integers (or double) and fail.

    Instead, if the server sends 49, which is related to the ascii character "1", the function toInt will return the number 1 (and ok=true).



  • Use QDataStream but you have to check the endinannes. I don't know what matlab uses, QDataStream will use Big-Endian by default, just as Matlab does, but you can change it with QDataStream::setByteOrder

    QDataStream socketStream(socket);
    double tempNumber = 0.0;
    for(;;){
    socketStream.startTransaction();
    socketStream >> tempNumber;
    if(socketStream.commitTransaction())
    qDebug() << "Received: " << tempNumber;
    else
    break;
    }
    

  • Qt Champions 2017

    @VRonin

    During my studies, our professor told us that the "convention" on Ethernet is Big Endian, which was funny as almost all computers at that time used Intel aka Little Endian architecture.

    But this is no iron law, and I'm currently working with a customer that demanded a Little Endian protocol. Well, it's on a RS-422 line, which transfers data LSB first, so you can at least read your data backwards on the line :)



  • @aha_1980 said in QTcpSocket: how to read numbers:

    During my studies, our professor told us that the "convention" on Ethernet is Big Endian

    That was probably the same professor the guys at MathWorks had, from
    https://uk.mathworks.com/help/instrument/read-and-write-binary-data-over-tcpip.html :

    You may need to configure the ByteOrder of the TCP/IP object. The ByteOrder property specifies the byte order of the server. By default ByteOrder is bigEndian



  • It works. Thank you very much guys.

    At first I "fixed" it by using the QChar class and the unicode function to get the value of every single byte and combine them. But it was a very inelegant solution and gave problems with numbers greater than 127.
    I tried the QDataStream too but it didn't work. Simply because my knowledge in Qt is at very beginner level and I didn't know how to use the QDataStream properly. I didn't know about the startTransaction and commitTransaction functions.
    Now it works good. Thank you :-)


  • Qt Champions 2017

    Hi @Davide87,

    well it's possible without QDataStream also. The problem with numbers > 127 results from QByteArray consisting of chars which most compilers treat as signed unfortunately. that can be solved with casting to unsigned char.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.