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 writeQByteArray 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, withqDebug() << 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.
-
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. -
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 codebool ok; int number = myData_element.toInt(&ok,10); qDebug() << myData_element << myData_element.data() << number << ok;
it will return:
"A" A 0 falseThis 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 withQDataStream::setByteOrder
QDataStream socketStream(socket); double tempNumber = 0.0; for(;;){ socketStream.startTransaction(); socketStream >> tempNumber; if(socketStream.commitTransaction()) qDebug() << "Received: " << tempNumber; else break; }
-
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 withQDataStream::setByteOrder
QDataStream socketStream(socket); double tempNumber = 0.0; for(;;){ socketStream.startTransaction(); socketStream >> tempNumber; if(socketStream.commitTransaction()) qDebug() << "Received: " << tempNumber; else break; }
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 :)
-
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 :-) -
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 :-)Hi @Davide87,
well it's possible without
QDataStream
also. The problem with numbers > 127 results fromQByteArray
consisting ofchar
s which most compilers treat as signed unfortunately. that can be solved with casting tounsigned char
.