Page 1 of 2 12 LastLast
Results 1 to 20 of 25

Thread: Formatting a packet with different types then send it over TCP

  1. #1
    Join Date
    Feb 2011
    Posts
    64
    Thanks
    16
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Formatting a packet with different types then send it over TCP

    I designed a simple protocol with this header:
    V(1 byte)|L(4 bytes):T(1 byte):D(variable)
    A real example will be like this packet:
    0xH112250xT1dfsdffdfsdfdsfdsffdsfdfsdf...
    So now to send it I do this:

    #define PROTO 0xH1
    #define TYPE 0xT1..

    Qt Code:
    1. QString query = "dfsfdsdfdsfdsf";
    2. QDataStream out(&msg, QIODevice::WriteOnly);
    3. out.setVersion(QDataStream::Qt_4_7);
    4. out << PROTO << (quint32)0 << TYPE << query;
    5. out.device()->seek(1);
    6. out << quint32(query.length() - sizeof(quint32));
    To copy to clipboard, switch view to plain text mode 

    The compilation error message said:
    Qt Code:
    1. guiclient.cpp:54: error: invalid suffix "xH1" on integer constant
    To copy to clipboard, switch view to plain text mode 
    So how I properly put hexadecimal in QDataStream?
    Last edited by SIFE; 1st June 2011 at 07:48.

  2. #2
    Join Date
    Mar 2009
    Location
    Brisbane, Australia
    Posts
    7,729
    Thanks
    13
    Thanked 1,610 Times in 1,537 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows
    Wiki edits
    17

    Default Re: Formatting a packet with different types then send it over TCP

    The error is exactly what the message says. 0xH1 is not a numeric literal in C++. Your compiler, trying to make the best of bad input, takes the leading zero as an int and then determines that xH1 is not a valid literal suffix.

    You probably meant:
    Qt Code:
    1. #define PROTO 0x1
    2. #define PROTO 0x01
    3. or
    4. #define PROTO 1
    To copy to clipboard, switch view to plain text mode 
    They are equivalent. You must take action to ensure that integer use of these literals is the single byte you are expecting (it won't be by default).

    You almost certainly do not want to use QDataStream unless the other end is a Qt program, and even then you should think twice. QDatastream does not dump the in-memory bytes to the stream, it serialises the objects concerned in object-defined ways. Just use the QIODevice methods directly to have direct control.

    You should also avoid using the pre-processor for constant in C++ code:
    http://www.parashift.com/c++-faq-lit...html#faq-29.11
    http://www.parashift.com/c++-faq-lit....html#faq-29.8
    Last edited by ChrisW67; 1st June 2011 at 05:08.

  3. The following user says thank you to ChrisW67 for this useful post:

    SIFE (2nd June 2011)

  4. #3
    Join Date
    Feb 2011
    Posts
    64
    Thanks
    16
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Formatting a packet with different types then send it over TCP

    I am defining my own protocol messages, so I have many byte's like 0xH1. I took a look at emule source code, and in opcodes.h header I found the developer's define messages types like this:
    Qt Code:
    1. #define EDONKEYVERSION 0x3C
    2.  
    3. #define KADEMLIA_VERSION1_46c 0x01 /*45b - 46c*/
    4.  
    5. #define KADEMLIA_VERSION2_47a 0x02 /*47a*/
    6.  
    7. #define KADEMLIA_VERSION3_47b 0x03 /*47b*/
    8.  
    9. #define KADEMLIA_VERSION5_48a 0x05 // -0.48a
    To copy to clipboard, switch view to plain text mode 
    So how do I make the compiler understand my own types like emule do?
    You almost certainly do not want to use QDataStream unless the other end is a Qt program, and even then you should think twice. QDatastream does not dump the in-memory bytes to the stream, it serialises the objects concerned in object-defined ways. Just use the QIODevice methods directly to have direct control.
    This is useful note, I didn't know it.

  5. #4
    Join Date
    Mar 2009
    Location
    Brisbane, Australia
    Posts
    7,729
    Thanks
    13
    Thanked 1,610 Times in 1,537 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows
    Wiki edits
    17

    Default Re: Formatting a packet with different types then send it over TCP

    Qt Code:
    1. So how do I make the compiler understand my own types like emule do?
    To copy to clipboard, switch view to plain text mode 
    Those things are not types, they are preprocessor symbols that are substituted literally wherever they appear after their declaration. You can define preprocessor symbols for constants exactly like emule does (and my previous reply indicates) if that is what you want. C++ has better methods for declaring a constant, but define works too.

    None of the symbols in the eMule example are in the form 0xH1 because that has never been a valid C or C++ integer constant. "0x" introduces a hex constant but "H" is not a hex digit.

  6. The following user says thank you to ChrisW67 for this useful post:

    SIFE (9th June 2011)

  7. #5
    Join Date
    Feb 2011
    Posts
    64
    Thanks
    16
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Formatting a packet with different types then send it over TCP

    You almost certainly do not want to use QDataStream unless the other end is a Qt program, and even then you should think twice. QDatastream does not dump the in-memory bytes to the stream, it serialises the objects concerned in object-defined ways. Just use the QIODevice methods directly to have direct control.
    Do you have any snippets for that.
    Now I am sending packet like this:
    Qt Code:
    1. void GuiClient::sendMsg()
    2. {
    3. QDataStream out(&msg, QIODevice::WriteOnly);
    4. out.setVersion(QDataStream::Qt_4_7);
    5. out << PROTO_VERSION << hex << (quint32)0 << MSG_TYPE << hex << ui->msgEdit->text().trimmed();
    6. out.device()->seek(1);
    7. out << quint32(msg.size() - sizeof(quint32));
    8.  
    9. qDebug("%d", msg.size());
    10.  
    11. client->write(msg);
    12. //V1-L4-T1-D~
    13. ui->msgEdit->clear();
    14. ui->msgEdit->setFocus();
    15. }
    To copy to clipboard, switch view to plain text mode 
    And to extract info from fields:
    Qt Code:
    1. void GuiServer::readMsg()
    2. {
    3. if(client) //user stored member variable, should be 0 if no client is connected
    4. {
    5. QDataStream in(client);
    6.  
    7. quint32 blockSize = 0;
    8.  
    9. while (client->bytesAvailable() < (int)sizeof(quint32) + 1) {
    10. if (!client->waitForReadyRead(2000)) {
    11. //emit error(client->error(), client->errorString());
    12. return;
    13. }
    14. }
    15.  
    16. unsigned char proto, msg_type;
    17.  
    18. in.setVersion(QDataStream::Qt_4_7);
    19.  
    20. in >> proto >> blockSize >> msg_type;
    21.  
    22. qDebug("%X", proto);
    23. qDebug("%X", msg_type);
    24. qDebug("%d", blockSize);
    25.  
    26. while (client->bytesAvailable() < blockSize) {
    27. if (!client->waitForReadyRead(2000)) {
    28. //emit error(socket.error(), socket.errorString());
    29. return;
    30. }
    31. }
    32.  
    33. QString msg;
    34.  
    35. in >> msg;
    36.  
    37. ui->historyEdit->append(msg);
    38. }
    39.  
    40. }
    To copy to clipboard, switch view to plain text mode 
    But this extract no proto, msg_type nor the msg except the size and time correctly and and time incorrectly.

  8. #6
    Join Date
    Mar 2009
    Location
    Brisbane, Australia
    Posts
    7,729
    Thanks
    13
    Thanked 1,610 Times in 1,537 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows
    Wiki edits
    17

    Default Re: Formatting a packet with different types then send it over TCP

    Here is your code in a self-contained example writing to a file:
    Qt Code:
    1. #include <QtCore>
    2. #include <QDebug>
    3.  
    4. #define PROTO_VERSION 1
    5. #define MSG_TYPE 34
    6. QString testMsg("This is a dummy message");
    7.  
    8. int main(int argc, char *argv[])
    9. {
    10. QCoreApplication app(argc, argv);
    11.  
    12. QDataStream out(&msg, QIODevice::WriteOnly);
    13. out.setVersion(QDataStream::Qt_4_7);
    14. out << PROTO_VERSION << hex << (quint32)0 << MSG_TYPE << hex << testMsg;
    15. out.device()->seek(1);
    16. out << quint32(msg.size() - sizeof(quint32));
    17.  
    18.  
    19. QFile f("/tmp/f.bin");
    20. if (f.open(QIODevice::WriteOnly)) {
    21. f.write(msg);
    22. f.close();
    23. }
    24.  
    25. return 0;
    26. }
    To copy to clipboard, switch view to plain text mode 

    First is the obvious problem of trying to use QTextStream::hex() on a QDataStream... yes, the warning messages your compiler is issuing mean something:
    Qt Code:
    1. main.cpp: In function ‘int main(int, char**)’:
    2. main.cpp:15: warning: the address of ‘QTextStream& hex(QTextStream&)’ will always evaluate as ‘true’
    3. main.cpp:15: warning: the address of ‘QTextStream& hex(QTextStream&)’ will always evaluate as ‘true’
    To copy to clipboard, switch view to plain text mode 

    You really need to understand the difference between a byte and the hexadecimal representation of that byte.
    You need to re-read my earlier advice about forcing the size of integers. PROTO_VERSION is written as four bytes (and partially overwritten) and MSG_TYPE is also 4 bytes. The value "true" referred to in the warning is written as a single byte.

    Look at the actual bytes you are sending by dumping the byte array. Inspect the stream byte-by-byte and then you will possibly understand why this is doomed to fail.

    Dumped binary file for you to analyse
    Qt Code:
    1. 0000000 00 00 00 00 3c 00 00 00 00 00 00 00 22 01 00 00
    2. nul nul nul nul < nul nul nul nul nul nul nul " soh nul nul
    3. 0000020 00 2e 00 54 00 68 00 69 00 73 00 20 00 69 00 73
    4. nul . nul T nul h nul i nul s nul sp nul i nul s
    5. 0000040 00 20 00 61 00 20 00 64 00 75 00 6d 00 6d 00 79
    6. nul sp nul a nul sp nul d nul u nul m nul m nul y
    7. 0000060 00 20 00 6d 00 65 00 73 00 73 00 61 00 67 00 65
    8. nul sp nul m nul e nul s nul s nul a nul g nul e
    To copy to clipboard, switch view to plain text mode 

    The "00 00 00 3c" (60 decimal) is the block size you wrote at offset 1, partially over the PROTO_VAR value.
    The "00 00 00 22" (34 decimal) in the first line is the MSG_TYPE.
    QDataStream serialises the QString class as a 4-byte size followed by the characters in in 16-bit chars. The 23 character string has a size of 46 bytes, "00 00 00 2e" in the listing.
    Last edited by ChrisW67; 7th June 2011 at 07:25.

  9. The following user says thank you to ChrisW67 for this useful post:

    SIFE (9th June 2011)

  10. #7
    Join Date
    Feb 2011
    Posts
    64
    Thanks
    16
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Formatting a packet with different types then send it over TCP

    I don't have any compiler warning, I forget to mention how PROTO_VERSION and MSG_TYPE how they are defined:
    Qt Code:
    1. #define PROTO_VERSION 0xA7
    2. #define MSG_TYPE 0xA8
    To copy to clipboard, switch view to plain text mode 
    In sendMsg SLOT, I can see 14 byte sent (12 bytes + 1 byte(PROTO_VERSION) + 1 byte(MSG_TYPE), with no text additional), but in the other side I don't know how to extract it correctly again.

  11. #8
    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: Formatting a packet with different types then send it over TCP

    Do you understand what QIODevice::seek() does? Do you understand the difference between QIODevice::write() and QDataStream's << operator? Do you understand how the compiler interprets number literals in code? What is the size (in bytes) of 0xA7 on a 32 bit machine?
    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.


  12. #9
    Join Date
    Mar 2009
    Location
    Brisbane, Australia
    Posts
    7,729
    Thanks
    13
    Thanked 1,610 Times in 1,537 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows
    Wiki edits
    17

    Default Re: Formatting a packet with different types then send it over TCP

    Quote Originally Posted by SIFE View Post
    I don't have any compiler warning, I forget to mention how PROTO_VERSION and MSG_TYPE how they are defined:
    Get a better compiler or turn on the warnings. The actual small values of PROTO_VERSION and MSG_TYPE are irrelevant to your problem.

    In sendMsg SLOT, I can see 14 byte sent (12 bytes + 1 byte(PROTO_VERSION) + 1 byte(MSG_TYPE), with no text additional), but in the other side I don't know how to extract it correctly again.
    As my example made with your code shows very clearly you are not sending anything like what you think you are sending. Before you use seek() and write the block size your buffer contains:
    1. Four bytes for PROTO_VERSION
    2. One byte 0x01 as a result of the "hex"
    3. Four zero bytes
    4. Four bytes for MSG_TYPE
    5. One byte 0x01 as as result of the "hex"
    6. Your serialised QString
      1. Four bytes string length in bytes. If you send an empty string this will still be present.
      2. Two bytes for each character in the string.

    When you seek and write the block size you overwrite the last three bytes of 1 and the byte at 2. The smallest this block will be is 18 bytes.

    Just because a number can fit into a single byte does not mean the compiler will do so. The default size of an integer literal is sizeof(int), typically four bytes although it could be 2 or 8.

  13. The following user says thank you to ChrisW67 for this useful post:

    SIFE (9th June 2011)

  14. #10
    Join Date
    Feb 2011
    Posts
    64
    Thanks
    16
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Formatting a packet with different types then send it over TCP

    I have generic information:
    Do you understand what QIODevice::seek() does?
    Move cursor to a specified position in stream.
    Do you understand the difference between QIODevice::write() and QDataStream's << operator?
    Not exactly, but I know QDataStream serializing data.
    Do you understand how the compiler interprets number literals in code?
    Not sure.
    What is the size (in bytes) of 0xA7 on a 32 bit machine?
    1 Byte.

  15. #11
    Join Date
    Mar 2009
    Location
    Brisbane, Australia
    Posts
    7,729
    Thanks
    13
    Thanked 1,610 Times in 1,537 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows
    Wiki edits
    17

    Default Re: Formatting a packet with different types then send it over TCP

    I suggest that you look at your last two answers in light of the blow-by-blow deconstruction I did in my last post and this test program:
    Qt Code:
    1. #include <iostream>
    2. #define PROTO_VERSION 0xA7
    3. int main(int argc, char *argv[]) {
    4. std::cout << sizeof(PROTO_VERSION) << std::endl
    5. << sizeof(static_cast<short>(PROTO_VERSION)) << std::endl
    6. << sizeof(static_cast<unsigned char>(PROTO_VERSION)) << std::endl;
    7. }
    To copy to clipboard, switch view to plain text mode 

  16. The following user says thank you to ChrisW67 for this useful post:

    SIFE (9th June 2011)

  17. #12
    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: Formatting a packet with different types then send it over TCP

    Quote Originally Posted by SIFE View Post
    I have generic information:

    Move cursor to a specified position in stream.
    Yes, in bytes. So seek(1) moves to the second byte in the stream. Compare that to the last question I asked and my response to it together with what Christ has written.

    Not exactly, but I know QDataStream serializing data.
    But you don't want to serialize data.

    Not sure.
    It interprets them as integers.

    1 Byte.
    No. 0xA7 is really (usually) 0x000000A7 on a 32 bit machine and it occupies four bytes.
    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.


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

    SIFE (9th June 2011)

  19. #13
    Join Date
    Feb 2011
    Posts
    64
    Thanks
    16
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Formatting a packet with different types then send it over TCP

    No. 0xA7 is really (usually) 0x000000A7 on a 32 bit machine and it occupies four bytes.
    I thought hexadecimal size is 4bits.
    I Understand I have to cast PROTO_VERSION to unsigned char so I can make 1 byte, I make this changes:
    Qt Code:
    1. void GuiClient::sendMsg()
    2. {
    3. QDataStream out(&msg, QIODevice::WriteOnly);
    4. out.setVersion(QDataStream::Qt_4_7);
    5. out <<static_cast<unsigned char> (PROTO_VERSION)
    6. << (quint32)0 << static_cast<unsigned char>(MSG_TYPE) << ui->msgEdit->text().toAscii().trimmed();
    7.  
    8. out.device()->seek(1);
    9. out << quint32(msg.size() - sizeof(quint32));
    10.  
    11. qDebug("%d", msg.size());
    12.  
    13. client->write(msg);
    14.  
    15. QFile f("test0" + QString::number(++i) + ".bin");
    16. if (f.open(QIODevice::WriteOnly)) {
    17. f.write(msg);
    18. f.close();
    19. }
    20.  
    21. ui->msgEdit->clear();
    22. ui->msgEdit->setFocus();
    23. }
    To copy to clipboard, switch view to plain text mode 

    Qt Code:
    1. void GuiServer::readMsg()
    2. {
    3. if(client) //user stored member variable, should be 0 if no client is connected
    4. {
    5. QDataStream in(client);
    6.  
    7. quint32 blockSize = 0;
    8.  
    9. while (client->bytesAvailable() < (int)sizeof(quint32) + 2) {
    10. if (!client->waitForReadyRead(2000)) {
    11. //emit error(client->error(), client->errorString());
    12. return;
    13. }
    14. }
    15.  
    16. unsigned char proto, msg_type;
    17.  
    18. in.setVersion(QDataStream::Qt_4_7);
    19.  
    20. in >> proto;
    21. in.device()->seek(1);
    22. in >> blockSize;
    23. in.device()->seek(1 + (int)sizeof(quint32));
    24. in >> msg_type;
    25.  
    26. qDebug("protocol %X", proto);
    27. qDebug("size %d", blockSize);
    28. qDebug("message type %X", msg_type);
    29.  
    30. while (client->bytesAvailable() < blockSize) {
    31. if (!client->waitForReadyRead(2000)) {
    32. //emit error(socket.error(), socket.errorString());
    33. return;
    34. }
    35. }
    36.  
    37. QString msg;
    38.  
    39. in.device()->seek(2 + (int)sizeof(quint32));
    40.  
    41. in >> msg;
    42.  
    43. ui->historyEdit->append(msg);
    44. }
    45.  
    46. }
    To copy to clipboard, switch view to plain text mode 
    The dump show this:
    Qt Code:
    1. $ hexdump -Cd test09.bin
    2. 00000000 a7 00 00 00 08 a8 00 00 00 02 2a 38 |..........*8|
    3. 0000000 00167 00000 43016 00000 00512 14378
    4. 000000c
    To copy to clipboard, switch view to plain text mode 
    What I miss here?

  20. #14
    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: Formatting a packet with different types then send it over TCP

    Quote Originally Posted by SIFE View Post
    I thought hexadecimal size is 4bits.
    What does it have to do with anything?

    What I miss here?
    You are still using QDataStream, which is not what you really want.
    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.


  21. #15
    Join Date
    Mar 2009
    Location
    Brisbane, Australia
    Posts
    7,729
    Thanks
    13
    Thanked 1,610 Times in 1,537 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows
    Wiki edits
    17

    Default Re: Formatting a packet with different types then send it over TCP

    Quote Originally Posted by SIFE View Post
    Qt Code:
    1. out <<static_cast<unsigned char> (PROTO_VERSION)
    2. << (quint32)0 << static_cast<unsigned char>(MSG_TYPE)
    3. << ui->msgEdit->text().toAscii().trimmed();
    4.  
    5. out.device()->seek(1);
    6. out << quint32(msg.size() - sizeof(quint32));
    To copy to clipboard, switch view to plain text mode 
    The dump show this:
    Qt Code:
    1. $ hexdump -Cd test09.bin
    2. 00000000 a7 00 00 00 08 a8 00 00 00 02 2a 38 |..........*8|
    3. 0000000 00167 00000 43016 00000 00512 14378
    4. 000000c
    To copy to clipboard, switch view to plain text mode 
    What I miss here?
    Nothing, it is outputting exactly what you told it to:
    a7 = PROTO_VERSION
    00 00 00 08 = block size (12) - sizeof(quint32)
    a8 = MSG_TYPE
    Serialised QByteArray:
    00 00 00 02 = length of array in bytes
    2a = '*'
    38 = '8'

  22. #16
    Join Date
    Jan 2011
    Posts
    34
    Thanks
    6
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Formatting a packet with different types then send it over TCP

    If you don't plan to send large binary data parts, JSON serialization will be the most convenient solution. Look at QJson library.

  23. #17
    Join Date
    Feb 2011
    Posts
    64
    Thanks
    16
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Formatting a packet with different types then send it over TCP

    What does it have to do with anything?
    This change the image of how hexadecimal represent it in 32-bit machine.
    You are still using QDataStream, which is not what you really want.
    Would you suggest a solution fit my need, I made this try. It looks send the formatted packet as I expect but I don't now how to parse it correctly in other side:
    Qt Code:
    1. void GuiClient::sendMsg()
    2. {
    3.  
    4. int n = ui->msgEdit->text().toAscii().trimmed().size();
    5.  
    6. msg.append(static_cast<unsigned char> (PROTO_VERSION));
    7.  
    8. for(int i2 = 0; i2 != sizeof(n); ++i2)
    9. {
    10. msg.append((char)(n&(0xFF << i2) >>i2));
    11. }
    12.  
    13. msg.append(static_cast<unsigned char>(MSG_TYPE));
    14. msg.append(ui->msgEdit->text().toAscii().trimmed());
    15.  
    16.  
    17. qDebug("%d", msg.size());
    18. qDebug("%s", msg.data());
    19.  
    20. client->write(msg);
    21.  
    22. QFile f("test0" + QString::number(++i) + ".bin");
    23. if (f.open(QIODevice::WriteOnly)) {
    24. f.write(msg);
    25. f.close();
    26. }
    27.  
    28. ui->msgEdit->clear();
    29. ui->msgEdit->setFocus();
    30. }
    To copy to clipboard, switch view to plain text mode 

    Qt Code:
    1. void GuiServer::readMsg()
    2. {
    3. if(client) //user stored member variable, should be 0 if no client is connected
    4. {
    5. int blockSize = 0;
    6.  
    7. while (client->bytesAvailable() < (int)sizeof(int) + 2) {
    8. if (!client->waitForReadyRead(2000)) {
    9. //emit error(client->error(), client->errorString());
    10. return;
    11. }
    12. }
    13.  
    14. QByteArray array(client->read(6));
    15.  
    16. QByteArray array2;
    17.  
    18. array2[0] = array[1];
    19. array2[1] = array[2];
    20. array2[2] = array[3];
    21. array2[3] = array[4];
    22.  
    23. memcpy(&blockSize, array2, sizeof(int));
    24.  
    25. int i = 0;
    26.  
    27. QFile f("test0" + QString::number(++i) + ".bin");
    28. if (f.open(QIODevice::WriteOnly)) {
    29. f.write(array);
    30. f.close();
    31. }
    32.  
    33. qDebug("msg %s", array.data());
    34. qDebug("protocol %s", array.data()[0]);
    35. qDebug("size %d", blockSize);
    36. qDebug("message type %s", array.data()[5]);
    37.  
    38. while (client->bytesAvailable() < blockSize) {
    39. if (!client->waitForReadyRead(2000)) {
    40. //emit error(socket.error(), socket.errorString());
    41. return;
    42. }
    43. }
    44.  
    45. QString msg;
    46.  
    47. ui->historyEdit->append(msg);
    48. }
    49. }
    To copy to clipboard, switch view to plain text mode 
    Hexdump shows:
    Client side:
    $ hexdump -Cb test01.bin
    Qt Code:
    1. 00000000 a7 05 05 05 05 a8 65 72 74 |......ert|
    2. 0000000 247 005 005 005 005 250 145 162 164
    3. 0000009
    To copy to clipboard, switch view to plain text mode 
    Server side:
    Qt Code:
    1. 00000000 a7 05 05 05 05 a8 |......|
    2. 0000000 247 005 005 005 005 250
    3. 0000006
    To copy to clipboard, switch view to plain text mode 
    It seems like the server can read the size of packet but it crashes when it tries to read data.
    I am in this project since week(trying to implement my protocol), google tired from me, and I am not sleep well because this(its like nightmare).

  24. #18
    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: Formatting a packet with different types then send it over TCP

    Quote Originally Posted by SIFE View Post
    This change the image of how hexadecimal represent it in 32-bit machine.
    No, it doesn't. The datatype states it is a "32 bit integer", it has nothing to do with its hexadecimal representation. You can as well represent it as 32 binary digits. Hex, bin or dec are just interpretations of the actual data stored in the computer memory according to internal representation chosen by the CPU and its compiler.

    I made this try.
    A very good try. You should have done that in the beginning.
    It looks send the formatted packet as I expect but I don't now how to parse it correctly in other side
    Exactly the same way you assemble the message on the sending side.

    If you send two bytes here, then you need to extract two bytes there, etc.

    I am in this project since week(trying to implement my protocol), google tired from me, and I am not sleep well because this(its like nightmare).
    Then take a piece of paper and draw a scheme of how your protocol is supposed to work and the bit-by-bit representation of its PDU. If you don't know how to do it, have a look at diagrams of standard binary protocols such as IP or NTP. If you google for "IP packet diagram", something meaningful will pop up. Practise with a raw stream of bytes until you learn to detect a beginning and end of each protocol unit in the raw stream. If you can't do it then probably the protocol lacks some necessary information and you have to adjust it accordingly.

    Only when you fully understand how your protocol should work (and why this and not some other way), then you may start writing an implementation. If you expect to talk to computers with different architecture, pay special attention to the byte order of words.
    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.


  25. #19
    Join Date
    Mar 2009
    Location
    Brisbane, Australia
    Posts
    7,729
    Thanks
    13
    Thanked 1,610 Times in 1,537 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows
    Wiki edits
    17

    Default Re: Formatting a packet with different types then send it over TCP

    The binary dumps show the size figure as "05 05 05 05" (hex), or 84 215 045 bytes, with a sent text message length of just three bytes. Something is wrong with your sending logic (Hint: shift by bytes not bits). Perhaps you should research the htonl() and ntohl() macros/functions.

    This thread is a reminder of why major high-level network protocols (SMTP, HTTP, NNTP, POP3, IMAP) are text-based and not binary. Not as efficient but a lot easier to get right.

  26. #20
    Join Date
    Feb 2011
    Posts
    64
    Thanks
    16
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Formatting a packet with different types then send it over TCP

    Then take a piece of paper and draw a scheme of how your protocol is supposed to work and the bit-by-bit representation of its PDU. If you don't know how to do it, have a look at diagrams of standard binary protocols such as IP or NTP. If you google for "IP packet diagram", something meaningful will pop up. Practise with a raw stream of bytes until you learn to detect a beginning and end of each protocol unit in the raw stream. If you can't do it then probably the protocol lacks some necessary information and you have to adjust it accordingly.

    Only when you fully understand how your protocol should work (and why this and not some other way), then you may start writing an implementation. If you expect to talk to computers with different architecture, pay special attention to the byte order of words.
    I already did that, now I am in the implementation, just because i am new to qt network programming.
    Now I have a problem in receiving data:
    Qt Code:
    1. void GuiServer::readMsg()
    2. {
    3. if(client) //user stored member variable, should be 0 if no client is connected
    4. {
    5. int blockSize = 0;
    6.  
    7. while (client->bytesAvailable() < (int)sizeof(int) + 2) {
    8. if (!client->waitForReadyRead(2000)) {
    9. //emit error(client->error(), client->errorString());
    10. return;
    11. }
    12. }
    13.  
    14. QByteArray data(client->read(6));
    15.  
    16. QByteArray array2;
    17. array2.reserve(4);
    18. array2[0] = data[1];
    19. array2[1] = data[2];
    20. array2[2] = data[3];
    21. array2[3] = data[4];
    22.  
    23. memcpy(&blockSize, array2, sizeof(int));
    24.  
    25. /* for (int j = 0; j < 4; ++j)
    26.   blockSize |= ((int)data[j] & 0x000000ff) << (j * 8);*/
    27.  
    28.  
    29. QFile f("test0" + QString::number(++i) + ".bin");
    30. if (f.open(QIODevice::WriteOnly)) {
    31. f.write(data);
    32. f.close();
    33. }
    34.  
    35. qDebug("size %d", blockSize);
    36. /*qDebug("msg %s", data.data());
    37.   qDebug("protocol %s", data.data()[0]);
    38.   qDebug("message type %s", data.data()[5]);
    39. */
    40. while (client->bytesAvailable() < blockSize) {
    41. if (!client->waitForReadyRead(2000)) {
    42. return;
    43. }
    44. }
    45.  
    46. QString msg(data);
    47.  
    48. ui->historyEdit->append(msg);
    49. }
    50. }
    To copy to clipboard, switch view to plain text mode 
    six-test.JPG
    I sent six messages from client, they all sent correctly however in the are side it seems like I receive the length first and if i sent another message from the client I receive the body. The photo from attachment shows how the server receive each message.

Similar Threads

  1. MAC address of UDP packet's sender
    By mastupristi in forum Qt Programming
    Replies: 3
    Last Post: 31st January 2011, 13:12
  2. Replies: 4
    Last Post: 10th December 2009, 16:37
  3. Packet getting fragmented when sending over QTcpSocket
    By arturo182 in forum Qt Programming
    Replies: 14
    Last Post: 5th August 2009, 23:11
  4. how to send ICMP packet
    By eleanor in forum Qt Programming
    Replies: 2
    Last Post: 30th October 2007, 14:23
  5. QtNetwork send ICMP Packet
    By SlowTree in forum Qt Programming
    Replies: 3
    Last Post: 29th October 2007, 20:13

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.