tags:

views:

71

answers:

3

I have a struct that I am sending to a UDP socket:

typedef struct
{
    char field_id;
    short field_length;
    char* field;
} field_t, *field_p;

I am able to read the field_id and field_length once received on the UDP server-side, however the pointer to field is invalid as expected.

What is the best method to properly send and receive a dynamic char*?

I have a basic solution using memcpy on the client side:

char* data = 
    (char*)malloc(sizeof(field_t) + (sizeof(char) *  strlen(my_field->field)));
memcpy(data, my_field, sizeof(field_t));
memcpy(data+sizeof(field_t), my_field->field, strlen(my_field->field) + 1);

And on the server side:

field_p data = (field_p)buffer;
field_string = (char*)buffer+sizeof(field_t);

Is there a cleaner way of doing this or is this the only way?

Thanks.

+2  A: 

You of course cannot send a pointer over a socket - get rid of the char* field; member. Instead, just append id and size pair with the data itself. Use writev(2) or sendmsg(2) to avoid moving data around from buffer to buffer.

Watch out for structure member alignment and padding and number endianness.

Nikolai N Fetissov
A slight bit of pedantry: you can send a pointer over a socket, but unless the other end of the socket is the same program, or something sharing the same memory space, it won't do you any good.
Jay Kominek
Yo can send yo mama over a socket :)
Nikolai N Fetissov
Matt Joiner
Oh, sockets work the other way around for aussies :)
Nikolai N Fetissov
+1 for the padding and endianness warning!
bstpierre
A: 

Serialization is your friend.

Related Links:

SO-1

SO-2

Praveen S
A: 

Define your structure as:

typedef struct
{
    uint8_t  field_id;
    uint16_t field_length;
    char     field[0]; // note: in C99 you could use char field[];
} field_t, *field_p;

Then, text buffer will immediately follow your structure. Just remember a few tricks:

// initialize structure
field_t *
field_init (uint8_t id, uint16_t len, const char *txt)
{
    field_t *f = malloc (sizeof (field_t + len)); // note "+ len";
    f->field_id  = id;
    f->field_length = len;
    memcpy (f->field, txt, len);
    return f;
}

// send structure
int
field_send (field_t *f, int fd)
{
    return write (fd, f, sizeof (*f) + f->field_length); // note "+ f->field_length"
}

I don't think it's standard, though. However, most compilers (GCC && MSVC) should support this. If your compiler does not support zero-sized array, you can use one-element char array - just remember to subtract extra one byte when calculating packet size.

el.pescado