Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing a structure through Sockets in C

I am trying to pass whole structure from client to server or vice-versa. Let us assume my structure as follows

struct temp {   int a;   char b; } 

I am using sendto and sending the address of the structure variable and receiving it on the other side using the recvfrom function. But I am not able to get the original data sent on the receiving end. In sendto function I am saving the received data into variable of type struct temp.

n = sendto(sock, &pkt, sizeof(struct temp), 0, &server, length); n = recvfrom(sock, &pkt, sizeof(struct temp), 0, (struct sockaddr *)&from,&fromlen); 

Where pkt is the variable of type struct temp.

Eventhough I am receiving 8bytes of data but if I try to print it is simply showing garbage values. Any help for a fix on it ?

NOTE: No third party Libraries have to be used.

EDIT1: I am really new to this serialization concept .. But without doing serialization cant I send a structure via sockets ?

EDIT2: When I try to send a string or an integer variable using the sendto and recvfrom functions I am receiving the data properly at receiver end. Why not in the case of a structure? If I don't have to use serializing function then should I send each and every member of the structure individually? This really is not a suitable solution since if there are 'n' number of members then there are 'n' number of lines of code added just to send or receive data.

like image 718
codingfreak Avatar asked Oct 16 '09 09:10

codingfreak


People also ask

How do you pass a structure in socket programming?

n = sendto(sock, &pkt, sizeof(struct temp), 0, &server, length); n = recvfrom(sock, &pkt, sizeof(struct temp), 0, (struct sockaddr *)&from,&fromlen); Where pkt is the variable of type struct temp.

How do you pass a structure to a function in C?

You can also pass structs by reference (in a similar way like you pass variables of built-in type by reference). We suggest you to read pass by reference tutorial before you proceed. During pass by reference, the memory addresses of struct variables are passed to the function.

Can you pass an entire structure to functions in C?

Passing of structure to the function can be done in two ways: By passing all the elements to the function individually. By passing the entire structure to the function.

What does socket () do in C?

The socket() function shall create an unbound socket in a communications domain, and return a file descriptor that can be used in later function calls that operate on sockets. The socket() function takes the following arguments: domain. Specifies the communications domain in which a socket is to be created.


1 Answers

This is a very bad idea. Binary data should always be sent in a way that:

  • Handles different endianness
  • Handles different padding
  • Handles differences in the byte-sizes of intrinsic types

Don't ever write a whole struct in a binary way, not to a file, not to a socket.

Always write each field separately, and read them the same way.

You need to have functions like

unsigned char * serialize_int(unsigned char *buffer, int value) {   /* Write big-endian int value into buffer; assumes 32-bit int and 8-bit char. */   buffer[0] = value >> 24;   buffer[1] = value >> 16;   buffer[2] = value >> 8;   buffer[3] = value;   return buffer + 4; }  unsigned char * serialize_char(unsigned char *buffer, char value) {   buffer[0] = value;   return buffer + 1; }  unsigned char * serialize_temp(unsigned char *buffer, struct temp *value) {   buffer = serialize_int(buffer, value->a);   buffer = serialize_char(buffer, value->b);   return buffer; }  unsigned char * deserialize_int(unsigned char *buffer, int *value); 

Or the equivalent, there are of course several ways to set this up with regards to buffer management and so on. Then you need to do the higher-level functions that serialize/deserialize entire structs.

This assumes serializing is done to/from buffers, which means the serialization doesn't need to know if the final destination is a file or a socket. It also means you pay some memory overhead, but it's generally a good design for performance reasons (you don't want to do a write() of each value to the socket).

Once you have the above, here's how you could serialize and transmit a structure instance:

int send_temp(int socket, const struct sockaddr *dest, socklen_t dlen,               const struct temp *temp) {   unsigned char buffer[32], *ptr;    ptr = serialize_temp(buffer, temp);   return sendto(socket, buffer, ptr - buffer, 0, dest, dlen) == ptr - buffer; } 

A few points to note about the above:

  • The struct to send is first serialized, field by field, into buffer.
  • The serialization routine returns a pointer to the next free byte in the buffer, which we use to compute how many bytes it serialized to
  • Obviously my example serialization routines don't protect against buffer overflow.
  • Return value is 1 if the sendto() call succeeded, else it will be 0.
like image 136
unwind Avatar answered Sep 24 '22 15:09

unwind