Efficient Packet Structures - Help?

Started by
29 comments, last by kurifu 22 years, 4 months ago
I have started to think about how I am going to format the incoming data packets (both UDP and TCP as the server will rely upon both protocols in different circumstances), and I seem to have come down to a few options.. however I am not presently satisfied with their efficiency and would like to ask for advice on more efficient packet stucturing, transmission, and receival. String Parsing Technique: I could just append all of the data, using wsprintf, into a text string and send that data. When the server receives this data it will parse the string, figure out what information is in the string, and make the appropriate changes. Only thing I do not like about this is that there will be an immense amount of work to parse the string and collect the data from it. Structure Tecnique: Well, as an attempt to not have to parse the strings from above, my other solution would be to create a structures for each type of outgoing packet, fill the structures, and read them back on the server end. The data is already sorted in the structure, however the problem that poses is... what structure am I supposed to be receiving? What happens if the packet is too large for the client? Another attempt at this would be to create a generic structure type with two fields, one a word, and the rest an array of char so that any data can be easily passed into it, and when the packet type is identified from the word, the data can be recasted into its proper structure type. Only problem I see here is that the full array of char will be transmitted, and may only contain 2 bytes of relevant data... this is a waste of bandwidth. I am not even entirely sure how much MSVC++ will like recasting the structures at that... Now, if I were to change that array of char to a pointer of char in the packet, though the pointer can hold a dynamic quantity of information, the problem comes that when you try to send the structure, the pointer address will be passed and not the information that it is pointing to (and will lead to a nice mess of random or corrupt data, and likely even an access violation). Anyone know of any good solutions to this problem or have any ideas? All help will be greatly appreciated. Sincerely, Clifford M. Roche Gamedev''s AI Auto-Reply bot.
Gamedev's AI Auto-Reply bot.
Advertisement
Use byte code.

sending
unsigned char message[maxmessagelength]

message[0]=40 ; //message type is 40 (player position)
message[1]=30 ; //player number 30
message[2]=100; //xpos = 100
message[3]=20; //ypos = 20

send(message, 4); //send four bytes of the message array

reciveing
switch(message[0])
{
case 40:
player[message[1]].xpos=message[2];
player[message[1]].ypos=message[3];
break;
}

I think you get the idea. The hard part is keeping track of what each byte of each message type represents.

Ben

That works along the lines of using the WORD header to describe the packet, and the array of char to send the data, only without recasting that data...

But the problem is that MAXMSGLEN could be (for example) 256bytes.

So when you send ( message, 4 ); you are truncating the outgoing structure.

When the server receives the data and you call

recv( SOCKET, &buffer, MAXMSGLEN ); you are trying to receive the entire buffer size, but will only be reciving part of it, will this not corrupt the data?

Gamedev''s AI Auto-Reply bot.
Gamedev's AI Auto-Reply bot.
I get it now...

And if I am concerned about data corruption, I can just memset ''\0'' the structure before receiving...

It bothers me that the solution was so simple, yet I neglected to find it...

Thanks in any case

Gamedev''s AI Auto-Reply bot.
Gamedev's AI Auto-Reply bot.
No, it seems that I can not recast these two structures:

typedef struct FOO1 {     WORD PacketID;     unsigned char Data[100];} UNIVERSALTCPPACKET; 


to

typedef struct FOO2 {     WORD PacketID;     char Data1[50];     char Data2[50];}How do games and game servers normally communicate with one another and avoid this problem?I think I am going to go read a little and see what other information I can find.    


Gamedev''s AI Auto-Reply bot.
Gamedev's AI Auto-Reply bot.
Tombstone uses the method I proposed and it works great. Winsock should report the size of the incomming packet.

Have you tried testing it to see if data is actually corrupted? For DPlay I don''t have to do anything special. It''s just basically doing a memcpy from the packet to the struct and if less comes in than space is avaiable then it doesn''t care.

Ben

Kurifu,

Just use a byte stream. Pack your structure members into a byte array, in a known order, so that the receiving end can unpack in the same order. Attach a header so you know the total size and the type of message. The actual code that does the recieving shouldn''t need to know about what it is receiving. This is how some commercial MMORPGs do it.
Fingh,

I have to disagree slightly. The receiving code needs to know a little bit about what is being transmitted if you are implementing guaranteed messaging via UDP. You need to check for data corruption/incomplete messages and manage ACKs for packets marked as guaranteed.

Obviously this could be abstracted to receiving the actual packet and the decoding of the received data.

Dire Wolf
www.digitalfiends.com
[email=direwolf@digitalfiends.com]Dire Wolf[/email]
www.digitalfiends.com
fing, essentially that is what I was doing, only I am casting the bytestream to a structure to more easily access the data, and have a universal header for all packets so that I may properly identify data such as wether to respond with an AK, and what kind of data is coming in (to know which packet to caste it to).



Gamedev''s AI Auto-Reply bot.
Gamedev's AI Auto-Reply bot.
You don''t really need to know what the data is, you just need the data itself to recalculate the checksum. This would obviously exclude the packet header (and therefore the sequence field and the crc) which he''s already determined to be of known size and composition. The difference, as you noted Dire, is that the header would be unpacked in the receiving code, but not necessarily the data itself (which is what I meant). Sorry if I caused some confusion, but I thought (based on previous posts) that the use of a packet header was implied.



This topic is closed to new replies.

Advertisement