Results 1 to 20 of 20

Thread: TCP Write Raw data

  1. #1
    Join Date
    Jan 2006
    Location
    Sta. Eugènia de Berga (Vic - Barcelona - Spain)
    Posts
    855
    Thanks
    68
    Thanked 56 Times in 54 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default TCP Write Raw data

    Hi,

    I'm trying to write raw data thorugh TCPSocket. I have a struct like (Modbus protocol):
    Qt Code:
    1. //Modbus header
    2. typedef struct MB_Request
    3. {
    4. uchar function_code;
    5. quint16 start_adr;
    6. quint16 quantity_regs;
    7. };
    8.  
    9. //Modbus/TCP header, containing the Modbus header
    10. typedef struct MBAP_Header
    11. {
    12. quint16 transaction_id;
    13. quint16 protocol_id;
    14. quint16 len;
    15. uchar unit_id;
    16. };
    17.  
    18. typedef struct MB_Message
    19. {
    20. MBAP_Header mb_hdr;
    21. MB_Request mb_req;
    22. };
    To copy to clipboard, switch view to plain text mode 

    What I don't know is how to send a variable (MB_Message type) as raw data. The documentation show that the data have to be stored as "char *". How have I to do this?

    Thanks,
    Òscar Llarch i Galán

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

    Default Re: TCP Write Raw data

    You can cast a pointer to the structure to char *, but beware that these structures are aligned and for example size of MB_Request is more than 5 bytes. If you use GCC you can add __attribute__((packed)) to pack them. Also make sure that integers have proper endianness.

  3. #3
    Join Date
    Jan 2006
    Location
    Sta. Eugènia de Berga (Vic - Barcelona - Spain)
    Posts
    855
    Thanks
    68
    Thanked 56 Times in 54 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: TCP Write Raw data

    Hi,

    You can cast a pointer to the structure to char *
    Qt Code:
    1. const char* data = (char*)&message;
    2. int ilen = strlen(data);
    3. tcpSocket->write(data,ilen);
    To copy to clipboard, switch view to plain text mode 

    Using this I only recive 1 byte.
    Maybe have I to create a "char*" containing the same values of the struct?

    Thanks,
    Òscar Llarch i Galán

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

    Default Re: TCP Write Raw data

    strlen() is for zero-terminated strings, not for data --- use sizeof message instead.

  5. #5
    Join Date
    Jan 2006
    Location
    Sta. Eugènia de Berga (Vic - Barcelona - Spain)
    Posts
    855
    Thanks
    68
    Thanked 56 Times in 54 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: TCP Write Raw data

    Hi,

    Ok, it seems to work now.
    When the reciver gets the raw data, I have to cast the data to a struct pointer. Right?

    The other question is:
    but beware that these structures are aligned and for example size of MB_Request is more than 5 bytes.
    Also make sure that integers have proper endianness
    What do you mean with that the structures are aligned? And how can I maintain the proper endianess, I think that I'm sending the data as big endian.

    Thanks,
    Òscar Llarch i Galán

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

    Default Re: TCP Write Raw data

    Quote Originally Posted by ^NyAw^ View Post
    What do you mean with that the structures are aligned?
    Check what sizeof( MB_Request ) returns. It contains only 5 bytes of data, yet it's bigger because of performance reasons (i.e. it contains holes between fields). Most likely the protocol expects packed data, so you have to tell your compiler to treat those structures differently.

    http://en.wikipedia.org/wiki/Data_structure_alignment

    Quote Originally Posted by ^NyAw^ View Post
    And how can I maintain the proper endianess, I think that I'm sending the data as big endian.
    QSysInfo::ByteOrder will tell you whether you are using big-endian or little-endian system and you have to convert values to endianness required by the protocol.

  7. #7
    Join Date
    Jan 2006
    Location
    Sta. Eugènia de Berga (Vic - Barcelona - Spain)
    Posts
    855
    Thanks
    68
    Thanked 56 Times in 54 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: TCP Write Raw data

    Hi,

    Check what sizeof( MB_Request ) returns. It contains only 5 bytes of data
    It returns me "14". The structs are 7 bytes(Modbus/TCP header) + 5 bytes (Modbus header) that sum 12. So I think that the struct "MB_Message" contains 1 byte for the first struct and another byte for the second struct.

    Thanks,
    Òscar Llarch i Galán

  8. #8
    Join Date
    Jan 2006
    Location
    Sta. Eugènia de Berga (Vic - Barcelona - Spain)
    Posts
    855
    Thanks
    68
    Thanked 56 Times in 54 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: TCP Write Raw data

    Hi,

    Ok, thanks for the link of "Data structure alignment".

    So, the "Modbus/TCP header" is 7 bytes. The "Modbus header" is 5 bytes. A total of 12 bytes that are 12*8 = 96 bits that are 32 bit aligned.
    So, why "sizeof(MB_Message)" is returning me 14 bytes?

    Thanks,
    Òscar Llarch i Galán

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

    Default Re: TCP Write Raw data

    Quote Originally Posted by ^NyAw^ View Post
    So, why "sizeof(MB_Message)" is returning me 14 bytes?
    Because there are one-byte holes after unit_id and function_code fields.

    I've attached a small application. It prints the addresses of all fields, so you can see how they're placed in the memory. If you use GCC, you can uncomment the #define in line 7 and comment out the one in line 6 to see how unaligned (a.k.a. packed) structures look like.
    Attached Files Attached Files

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

    ^NyAw^ (23rd November 2007)

  11. #10
    Join Date
    Jan 2006
    Location
    Sta. Eugènia de Berga (Vic - Barcelona - Spain)
    Posts
    855
    Thanks
    68
    Thanked 56 Times in 54 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: TCP Write Raw data

    Hi,

    Ok, so every struct have to be 32-bit aligned.

    Thanks,
    Òscar Llarch i Galán

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

    Default Re: TCP Write Raw data

    Quote Originally Posted by ^NyAw^ View Post
    Ok, so every struct have to be 32-bit aligned.
    Yes, but only in memory on 32-bit (and pseudo-64bit) machines. Other machines might have different alignment. Also usually you don't align data in files* or in network communication.

    * Unless the file format was designed for fast access.

  13. #12
    Join Date
    Jan 2006
    Location
    Sta. Eugènia de Berga (Vic - Barcelona - Spain)
    Posts
    855
    Thanks
    68
    Thanked 56 Times in 54 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: TCP Write Raw data

    Hi,

    Yes, but only in memory on 32-bit (and pseudo-64bit) machines
    Of course, of course. Them are 32-bit aligned because of using 32-bit processor.

    Another question. I'm compiling the program with Visual Studio 2003 .NET and when using GNU/Linux I will have to compile with GCC, will the behavior be different? I'm asking this because I don't know what "__attribute__((packed))" do.

    Thanks,
    Òscar Llarch i Galán

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

    Default Re: TCP Write Raw data

    Quote Originally Posted by ^NyAw^ View Post
    I'm compiling the program with Visual Studio 2003 .NET and when using GNU/Linux I will have to compile with GCC, will the behavior be different? I'm asking this because I don't know what "__attribute__((packed))" do.
    __attribute__((packed)) is a GCC extension, so it won't work with VS. Basicly it sets the packed attribute for given class, which tells the compiler not to align it. It's perfect when you want to sent your structure directly over the network or read/write it from/to a file, but it's also completely unportable.

    VS probably has something different that will allow you to pack the structure. Since it's .NET, it might have a form of some annotation.

  15. #14
    Join Date
    Jan 2006
    Location
    Sta. Eugènia de Berga (Vic - Barcelona - Spain)
    Posts
    855
    Thanks
    68
    Thanked 56 Times in 54 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: TCP Write Raw data

    Hi,

    Ok, so it's only important because of the data that will be sent becomes longer and it could be smaller. So if I force to not pack, send it, and recive to another program that loads the data into the struct, the struct will contain the same data.
    But if forcing not to align the data, when using the variables in memory will produce TLB miss or a page faults (from the link of "Data structure alignment").

    Thank you very much,
    Òscar Llarch i Galán

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

    Default Re: TCP Write Raw data

    Quote Originally Posted by ^NyAw^ View Post
    Ok, so it's only important because of the data that will be sent becomes longer and it could be smaller.
    It isn't about sending few bytes less, but about adhering to given protocol. If it requires you to send a one-byte field followed by two-byte one, you can't send 1B of data, 1B of garbage and then 2B of data. If you use some custom protocol and both sender and receiver follow the same rules of alignment, you don't have to worry about it, but if you want to implement Modbus, you have to follow its specification and there are no holes in Modbus messages.

    Quote Originally Posted by ^NyAw^ View Post
    But if forcing not to align the data, when using the variables in memory will produce TLB miss or a page faults
    Yes, some CPUs can't even fetch unaligned data from memory, so accesses to such structures might be split into several operations.

  17. #16
    Join Date
    Jan 2006
    Location
    Sta. Eugènia de Berga (Vic - Barcelona - Spain)
    Posts
    855
    Thanks
    68
    Thanked 56 Times in 54 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: TCP Write Raw data

    Hi,

    Searching for the web I found this two helpful links (for Visual Studio compiler):
    http://msdn2.microsoft.com/en-us/lib...65(VS.80).aspx
    http://msdn2.microsoft.com/en-us/lib...y1(VS.80).aspx

    The second one works for me:
    Qt Code:
    1. #pragma pack(1)
    2. struct MB_Request
    3. {
    4. uchar function_code;
    5. quint16 start_adr;
    6. quint16 quantity_regs;
    7. };
    8.  
    9. #pragma pack(1)
    10. struct MBAP_Header
    11. {
    12. quint16 transaction_id;
    13. quint16 protocol_id;
    14. quint16 len;
    15. uchar unit_id;
    16. };
    17.  
    18. #pragma pack(1)
    19. struct MB_Message
    20. {
    21. MBAP_Header mb_hdr;
    22. MB_Request mb_req;
    23. };
    To copy to clipboard, switch view to plain text mode 

    Then, executing your example code, the structs are unaligned as I need for Modbus protocol.

    Could I use "#ifndef" statment to know wich compiler is used to then use "#pragma pack(1)" or "__attribute__((packed))" depending on compiler?
    So when I use GCC on GNU/Linux(or windows also) it will pack the data unaligned as expected. Could use GCC with Visual Studio?

    Thanks,

    Thanks,
    Òscar Llarch i Galán

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

    Default Re: TCP Write Raw data

    Quote Originally Posted by ^NyAw^ View Post
    Could I use "#ifndef" statment to know wich compiler is used to then use "#pragma pack(1)" or "__attribute__((packed))" depending on compiler?
    Yes, but using __desclspec(align(1)) might be more cleaner, because you will need only two macros (depending on the compiler one of them will be empty), instead of ifdef before each structure.

    Quote Originally Posted by ^NyAw^ View Post
    Could use GCC with Visual Studio?
    AFAIR it's possible, but I don't use VS, so I can't help you with that.

  19. #18
    Join Date
    Jan 2006
    Location
    Sta. Eugènia de Berga (Vic - Barcelona - Spain)
    Posts
    855
    Thanks
    68
    Thanked 56 Times in 54 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: TCP Write Raw data

    Hi,

    Yes, but using __desclspec(align(1)) might be more cleaner
    I've tryied this:
    Qt Code:
    1. __declspec(align(1)) struct MB_Request
    2. {
    3. uchar function_code;
    4. quint16 start_adr;
    5. quint16 quantity_regs;
    6. };
    7.  
    8. int main()
    9. {
    10. int iA1 = __alignof(MBAP_Header); // This returns "2" byte alignment and using #pragma pack(1) returns me "1" " byte alignment
    11. }
    To copy to clipboard, switch view to plain text mode 

    instead of ifdef before each structure
    I've found that GCC also supports this #pragma for compatibility with Win32:
    http://gcc.gnu.org/onlinedocs/gcc/St...g-Pragmas.html

    Thanks,
    Òscar Llarch i Galán

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

    Default Re: TCP Write Raw data

    Quote Originally Posted by ^NyAw^ View Post
    __declspec(align(1)) struct MB_Request
    ...
    int iA1 = __alignof(MBAP_Header); // This returns "2" byte
    Have you placed __declspec before MBAP_Header too?

    Quote Originally Posted by ^NyAw^ View Post
    I've found that GCC also supports this #pragma for compatibility with Win32
    In that case, you don't need any ifdefs.

  21. #20
    Join Date
    Jan 2006
    Location
    Sta. Eugènia de Berga (Vic - Barcelona - Spain)
    Posts
    855
    Thanks
    68
    Thanked 56 Times in 54 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: TCP Write Raw data

    Hi,

    Have you placed __declspec before MBAP_Header too?
    Yes:
    Qt Code:
    1. //#pragma pack(1)
    2. __declspec(align(1)) struct MB_Request
    3. {
    4. uchar function_code;
    5. quint16 start_adr;
    6. quint16 quantity_regs;
    7. };
    8.  
    9. //#pragma pack(1)
    10. __declspec(align(1)) struct MBAP_Header
    11. {
    12. quint16 transaction_id;
    13. quint16 protocol_id;
    14. quint16 len;
    15. uchar unit_id;
    16. };
    17.  
    18. //#pragma pack(1)
    19. __declspec(align(1)) struct MB_Message
    20. {
    21. MBAP_Header mb_hdr;
    22. MB_Request mb_req;
    23. };
    To copy to clipboard, switch view to plain text mode 

    But
    Qt Code:
    1. int iA1 = __alignof(MBAP_Header);
    2. int iA2 = __alignof(MB_Request);
    3. int iA3 = __alignof(MB_Message);
    To copy to clipboard, switch view to plain text mode 
    Returns always "2" for iA1, iA2 and iA3.

    Don't worry about it, using "#pragma pack(1)" is going well.

    Thanks for your time and your knowdelege.
    Òscar Llarch i Galán

Similar Threads

  1. Replies: 4
    Last Post: 19th October 2007, 19:47
  2. Data model
    By steg90 in forum Qt Programming
    Replies: 3
    Last Post: 17th September 2007, 12:14
  3. FSWriteFork in MAC OS to write data to a file.
    By vishal.chauhan in forum General Programming
    Replies: 5
    Last Post: 2nd July 2007, 06:48
  4. speed of setdata - lots of items in treeview
    By Big Duck in forum Qt Programming
    Replies: 4
    Last Post: 6th July 2006, 12:53
  5. Replies: 16
    Last Post: 7th March 2006, 15:57

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.