use some type of list to store various structs in byte form

Started by
6 comments, last by yewbie 15 years, 2 months ago
Well what I was going to try to do didn't actually work how I planned.. well because I can't use a list of pointers when the data gets removed after my function completes, so im looking for any suggestions. here is what I was doing: create a struct (actually server struts with different sizes and members, and I would create a list like so

typedef list<char*> tStructList;
typedef tStructList::iterator tStructIterator;
tStructList structlist;	
and add to the list like so structlist.push_front((char*)&mydatastruct); &mydatastruct is a pointer to my actual struct and when my function completes I just have a reference to mydatastruct that is actually not there :( is there anyway I can memcpy a struct to something and be able to convert it back to the struct without any data being lost? would something like work??

struct MYSTRUCT
{
  WORD a;//2 bytes
  WORD b;//2 bytes
}mystruct;
char test[4];
memcpy(test,mystruct,sizeof(mystruct));
I tried doing the same thing with list with a char[blah] but it doesn't allow me to use that :/ any suggetions will be appreciated! [Edited by - yewbie on January 25, 2009 10:55:29 PM]
Advertisement
Why do you need to store different stucts in the same list? And once you add them to the list, how will you know which type of struct a given list entry points to?

Quote:Original post by yewbie
and add to the list like so
structlist.push_front((char*)&mydatastruct);


Is mydatastruct on the stack? If so, as soon as it goes out of scope, it will be destroyed, and the pointer to it in the list will be pointing at garbage.
Quote:Original post by Driv3MeFar
Why do you need to store different stucts in the same list? And once you add them to the list, how will you know which type of struct a given list entry points to?

Basically im kinda doing something like a packet pump for winsock sending an receiving structs of data from my packets using SOCK_STREAM so its guaranteed delivery of the full packet, I receive my data packet typecast out the first WORD to get my packet and typecast out my second WORD to get my packet size, im just trying to have list of the packets I have received stored so that I can process through them.

when the data gets sent through winsock you send it as a typecast char* then re receive it and typecast it back to your struct and it works perfectly I just need a way to locally keep track of the various structs I have received in some type of list is all

Quote:
Is mydatastruct on the stack? If so, as soon as it goes out of scope, it will be destroyed, and the pointer to it in the list will be pointing at garbage.


Yeah thats what I ran into
Well im not sure if im on the right track or not but here is what im trying I did a test version of this and it worked out great

make a packet structure inside my player class (right now I have it just set as a single struct) but im thinking a array of this struct inside the class to hold up to 100 packets or more for each player kinda like a que

packet.data=false;
packet.size=0;
memset(packet.packetbuffer,0,200); //zero out our packet buffer

and I can copy my struct to it like so
memcpy(player->packet.packetbuffer,&mypacket,sizeof(PACKETID2));

and actually while typing this out I can't seem to get a array of structs to work as part of my class :/ I guess I will have to work some more on it tommorrow I think im on the right track though.

maybe just have a huge packetbuffer like 20000 bytes
read my first WORD which is the size of the first packet

memcpy(singlepacketbuffer,packetbuffer,mysizefrombuffer)
and just loop that untill there is no data in the buffer and add new data to the end as we receive data?
template<typename T>const char *mem_begin(const T& t) { return reinterpret_cast<const char*>(&t); }template<typename T>const char *mem_end(const T& t) { return reinterpret_cast<const char*>(&t + 1); }// Usage example:A a;B b;std::vector<char> data;data.insert(data.end(), mem_begin(a), mem_end(a));data.insert(data.end(), mem_begin(b), mem_end(b));
The general approach is to serialize into some kind of buffer object (a std::vector<char> is usually a good bet for the buffer), and then store the buffer. (You can't use 'char *' as your buffer type because it's just a pointer rather than the actual buffer; and arrays have their own tricky issues; better to use something that's a real object.) Then you deserialize to recreate the original object.

ToohrVyk's code shows the simplest possible approach to serialization - copying the actual bytes of the structure - which will work in some limited cases. Read the link for more information.

(We can go one step further and define a helper function:

// Only works with structure data that is POD and self-identifying.template <typename T>std::vector<char> serialize(const T& t) {  return std::vector<char>(mem_begin(t), mem_end(t));}


But why do you need to store the structs in a list at all? Why not just send each message as it's created?
Quote:Original post by Zahlman
need to store the structs in a list at all? Why not just send each message as it's created?


I guess I really don't have to at all, while I was at work I was considering just using a large buffer since the first 2 bytes of each packet are always going to be my size of the packet I can just copy out that portion, but I actually was just reading about what Zahlman was talking about at work on my lunch break and think that might work out for what im doing, I will hopefully get some code time tonight to try it out! thanks for the reply's guys!

basically I want the packets to be stored into something like a message queue where I can read packets in the order received easily, or even from another thread if I wanted to.
Basically here is what I ended up doing, it may not be the best way of doing it but its working perfectly (Im not super familiar with C++ yet I could not get the vector solution to work)

I have a large char SendBuffer[MAX_PACKET_SIZE];
anytime I had a packet I memcpy the struct to my buffer like so
memcpy(p->SendPacketBuffer,(char*)&mypacket,sizeof(PACKETID2));


then when im getting ready to send it to the client I do this
the first WORD in my packet is always the size so I take that out like so
WORD* PTR_Size = (WORD*)p->SendPacketBuffer;WORD PacketSize = *PTR_Size;


then I send it like so
int bytessent = send(p->s,(char*)&p->SendPacketBuffer, PacketSize, NULL); 


then I make sure data got sent and if it did then I do this
char temp[MAX_SENDPACKET];memcpy(temp,(char*)&p->SendPacketBuffer + bytessent, sizeof(p->SendPacketBuffer -bytessent));memcpy(p->SendPacketBuffer,temp,MAX_SENDPACKET);


seems to be working pretty good, any major flaws with using this method?

when I get the data on my client I dump everything into the same type of buffer get the first WORD and if I have enough data to fill out my struct I typecast it to the packettype struct and use it.

This topic is closed to new replies.

Advertisement