Lately I’ve been diving into network programming, and I’m having some difficulty constructing a packet with a variable “data” property. Several prior questions have helped tremendously, but I’m still lacking some implementation details. I’m trying to avoid using variable sized arrays, and just use a vector. But I can’t get it to be transmitted correctly, and I believe it’s somewhere during serialization.
Now for some code.
Packet Header
class Packet {
public:
void* Serialize();
bool Deserialize(void *message);
unsigned int sender_id;
unsigned int sequence_number;
std::vector<char> data;
};
Packet ImpL
typedef struct {
unsigned int sender_id;
unsigned int sequence_number;
std::vector<char> data;
} Packet;
void* Packet::Serialize(int size) {
Packet* p = (Packet *) malloc(8 + 30);
p->sender_id = htonl(this->sender_id);
p->sequence_number = htonl(this->sequence_number);
p->data.assign(size,'&'); //just for testing purposes
}
bool Packet::Deserialize(void *message) {
Packet *s = (Packet*)message;
this->sender_id = ntohl(s->sender_id);
this->sequence_number = ntohl(s->sequence_number);
this->data = s->data;
}
During execution, I simply create a packet, assign it’s members, and send/receive accordingly. The above methods are only responsible for serialization. Unfortunately, the data never gets transferred.
Couple of things to point out here. I’m guessing the malloc is wrong, but I’m not sure how else to compute it (i.e. what other value it would be). Other than that, I’m unsure of the proper way to use a vector in this fashion, and would love for someone to show me how (code examples please!) 🙂
Edit: I’ve awarded the question to the most comprehensive answer regarding the implementation with a vector data property. Appreciate all the responses!
This cast is very dangerous as you have allocated some raw memory and then treated it as an initialized object of a non-POD class type. This is likely to cause a crash at some point.
Looking at your code, I assume that you want to write out a sequence of bytes from the
Packetobject that the seralize function is called on. In this case you have no need of a second packet object. You can create a vector of bytes of the appropriate size and then copy the data across.e.g.
This may not be exactly what you intended as I’m not sure what the final object of your
sizeparameter is and your interface is potentially unsafe as you return a pointer to raw data that I assume is supposed to be dynamically allocated. It is much safer to use an object that manages the lifetime of dynamically allocated memory then the caller doesn’t have to guess whether and how to deallocate the memory.Also the caller has no way of knowing how much memory was allocated. This may not matter for deallocation but presumably if this buffer is to be copied or streamed then this information is needed.
It may be better to return a
std::vector<char>or to take one by reference, or even make the function a template and use an output iterator.