So I am trying to send a message to a client using the sendto() function.
The sendto() function's prototype is this:
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
const struct sockaddr *dest_addr, socklen_t addrlen);
But I would like to send a structure as the second argument. Is it possible for me to do that? Or does buf have to be a string?
EDIT: You see, I have to be able to send this:
"A message consists of "HEADER" followed by "PAYLOAD".
Your message header should consist of the following:
uint8_t version; /* must be 1. If you receive anything else, discard*/
uint8_t ttl; /* must be 1. If you receive anything else, discard*/
uint16_t payload_length; /* bytes following the header */
uint32_t account_identifier; /* digits of your account name */
uint32_t source_address; /* unused for now, set to 0 and ignore. */
uint32_t destination_address; /* unused for now, set to 0 and ignore. */
uint16_t checksum; /* unused for now, set to 0 and ignore. */
uint16_t protocol; /* must be 1. If you receive anything else, discard*/"
And payload is a text string like "Hello" or something.
I feel like the only way for me to send the header would be to send a struct of all that info. Right?
You can send any contiguous block of memory with sendto
, so a struct
with no pointers would be fine. However, the client needs to be able to process that struct
using the proper layout, which is extremely limiting.
Consider a simple struct
like this:
struct One {
int a;
float b;
char c[20];
};
It works fine on the same hardware, when the client and the server code are compiled with the same compiler, using identical settings. A slightly different hardware will cause issues even for this seemingly simple struct
, though: endianness, padding, the size of various representations, and so on, will all be the same in order for this to work.
If you need interoperability with other hardware or with other programming languages, you need to produce a specific structure, binary or a textual, that both sides can process.
If your struct
has a pointer, you would not be able to send and receive it without some special processing:
struct Two {
int a;
float b;
char* c; // <<<=== Not going to work
};
When you need to send structures like that, you "serialize" them on the sender into an array of bytes that can be "deserialized" by the receiving end, and send that buffer instead. The code that receives this buffer "unpacks" the data into a `struct", allocates memory as needed, and copies the data from the receiver buffer into this newly allocated memory.
The struct
above could be serialized as follows:
int
float
len
of the block pointed to by the pointer c
len
bytes representing the content of c