Improved Networking

Published: 16-Jan-2022

All iterations of this client and server have used C structures to arrange data to be sent over the network. While this was nice from a programming point of view, it was inefficient for the network.


Well, typically, when you work in C, you use structures like the following:

typedef struct PacketTypeSignUpS {
    char *user;
    char *pass;
    char *first;
    char *last;
    char *email;
} PacketTypeSignUpT;

What this means is that everything we need to know about a user to sign up for the service is contained in a nice little bundle named PacketTypeSignUpT. Great! You then allocate memory for each of the items and copy your data in there.

Unfortunately, when you allocate every item on it's own like this, the computer will locate it in the most efficient place in memory. For a network packet, this is bad. We need all our data to be in one big contiguous block.

We can fix this by allocating all the bits of data at once:

typedef struct PacketTypeSignUpS {
    char user[PACKET_MAX_USER];
    char pass[PACKET_MAX_PASS];
    char first[PACKET_MAX_NAME];
    char last[PACKET_MAX_NAME];
    char email[PACKET_MAX_EMAIL];
} PacketTypeSignUpT;

Now, everything is all smushed together in one giant block. We can send it across the wire in one piece. This is good! Except for the "giant" part. What if my name is Ed and PACKET_MAX_USER is 32 characters? We'd be wasting 30 bytes - in just one field!

While this isn't the end of the world, considering network speeds today, it's always bothered me, so I set out to fix it. The solution? A new pack/unpack feature in our packet API. Here's an example from the client:

packetData = packetContentPack(&length, "sssss",

What this does is take all the values that have been typed into the various text boxes in the sign up window and combines them together into packetData. We're provided the size of the result in length. Then, to undo this on the server side, we do:

packetContentUnpack(data->data, "sssss", &email, &first, &last, &pass, &user);

Our combined data is in data->data, we want to unpack five strings (the five s's), and store them in the named variables.

Easy, clean, and no wasted bytes!