Creating and sending data packets in C/C++

Well, typically it would look like it's preparing that packet structure into a memory buffer (making judicious calls the the htonl family of functions).

If would then use the send, sendto, sendmsg or write functions, hopefully with a lot of care taken with the length of the buffer and good error handling/reporting.

(Or one of the Win32 apis for the send, if that is the target plateforms.)

You'll find a good presentation about all this at Beej's Guide to Network Programming.

Specifially for the byte packing part (with endian consideration), look at the serialization topic. (There's way more detail in that section than what you need for plain fixed-size integer data types.


Let's suppose that your program is already organized to have the header in one struct and the data in another struct. For example, you might have these data structures:

#include <stdint.h>
struct header {
    uint16_t f1;
    uint16_t f2;
    uint32_t f3;
};
struct data {
    uint16_t pf1;
    uint64_t pf2;
};

Let's call this organization "host format". It really doesn't matter to me what the host format is, as long as it is useful to the rest of your program. Let's call the format that you will pass to the send() call "network format". (I chose these names to match the htons (host-to-network-short) and htonl (host-to-network-long) names.)

Here are some conversion functions that we might find handy. Each of these converts your host format structures to a network format buffer.

#include <arpa/inet.h>
#include <string.h>
void htonHeader(struct header h, char buffer[8]) {
    uint16_t u16;
    uint32_t u32;
    u16 = htons(h.f1);
    memcpy(buffer+0, &u16, 2);
    u16 = htons(h.f2);
    memcpy(buffer+2, &u16, 2);
    u32 = htonl(h.f3);
    memcpy(buffer+4, &u32, 4);
}
void htonData(struct data d, char buffer[10]) {
    uint16_t u16;
    uint32_t u32;
    u16 = htons(d.pf1);
    memcpy(buffer+0, &u16, 2);
    u32 = htonl(d.pf2>>32);
    memcpy(buffer+2, &u32, 4);
    u32 = htonl(d.pf2);
    memcpy(buffer+6, u32, 4);
}
void htonHeaderData(struct header h, struct data d, char buffer[18]) {
    htonHeader(h, buffer+0);
    htonData(d, buffer+8);
}

To send your data, do this:

...
char buffer[18];
htonHeaderData(myPacketHeader, myPacketData, buffer);
send(sockfd, buffer, 18, 0);
...

Again, you don't have to use the header and data structs that I defined. Just use whatever your program needs. The key is that you have a conversion function that writes all of the data, at well-defined offsets, in a well-defined byte order, to a buffer, and that you pass that buffer to the send() function.

On the other side of the network connection, you will need a program to interpret the data it receives. On that side, you need to write the corresponding functions (ntohHeader, etc). Those function will memcpy the bits out of a buffer and into a local variable, which it can pass to ntohs or ntohl. I'll leave those functions for you to write.

Tags:

C++

C

Sockets