Mahesh Khanal
Mahesh Khanal

Reputation: 13

How to send a struct over UDP and receive on the other side?

I have a very specific question on socket programming. My code is similar to the following.

struct data_packet{
   unsigned char seqnumber; 
   char data[500]; 
}

struct data_packet packettosend; 
packettosend.seqnumber = '0'
packettosend.data = 'some binary data' (this could be any length from 0 bytes to 500 bytes) 

//sender code 
char buffer[501]; 
memcpy(buffer, &packettosend, sizeof(packetosend)); 
int s = sendto(socketfd, buffer, sizeof(buffer), 0 , .......other params); 

//receiver code
char recvbuffer[501];
int t = recvfrom(recvsocketdf, recvbuffer, 501, 0 ....other params);
  
How do I set up my receiver to receive the data and save it on a `struct data_packet`?    

The seqnumber is a 1-byte char, and data could be 0 byte to 500 bytes.

I am using sendto to send the buffer and recvfrom to receive the buffer on the other end.

How do I receive my seqnumber and data on the receiving end? I am very new to C and Socket programming. I appreciate any help.

Upvotes: 1

Views: 2236

Answers (3)

user14820413
user14820413

Reputation:

I concur with Dennis Afanasev. To elaborate on the casting strategy, read all 501 bytes (including partial/incomplete reads) then cast into the pointer variable e.g.:

struct data_packet *dataRecv = (struct data_packet *)&recvbuffer[0];

Then you can dereference dataRecv to access the struct, as in dataRecv->seqnumber and dataRecv->data.

Upvotes: 0

chux
chux

Reputation: 153328

Possible problem:

Code likely writes outside its bounds due to struct padding.

struct data_packet{
   unsigned char seqnumber; 
   // There maybe padding here.
   char data[500]; 
   // There maybe padding here.
}

struct data_packet packettosend; 
char buffer[501];  // May be too small for `packettosend`
memcpy(buffer, &packettosend, sizeof(packetosend)); 

Alternative: Make buffer[] certainly big enough

// char buffer[501];
char buffer[sizeof packetosend];

To send just the data and not certainly not any padding:

Pack the data with an implementation specific keyword (if available)

// struct data_packet{
packed struct data_packet{

Or perform 2 sends

int s1 = sendto(socketfd, &buffer.seqnumber, sizeof buffer.seqnumber, ...);
int s2 = sendto(socketfd, buffer.data, sizeof buffer.data, ...);

Or copy carefully

#define SEQ_DATA (sizeof buffer.seqnumber + sizeof buffer.data)
char buffer[SEQ_DATA]; 
memcpy(buffer, &buffer.seqnumber, sizeof buffer.seqnumber);
memcpy(buffer + sizeof buffer.seqnumber, buffer.data, sizeof buffer.data);
int s = sendto(socketfd, buffer, sizeof buffer, ...);

Adjust recvbuffer[] size to match.

Upvotes: 1

Dennis Afanasev
Dennis Afanasev

Reputation: 89

My first suggestion is to zero out your buffer before filling it in and sending it out, just to avoid garbage values. And you need to define a protocol - you can only send and receive raw bytes over the network. Make it so that the receiving end interprets the first byte as the sequence number, and the rest as the actual message itself. This can be done by simply casting the recvbuffer into a struct data_packet, as the underlying byte layout is the same.

Upvotes: 1

Related Questions