🎉 Celebrating 25 Years of GameDev.net! 🎉
Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!
WinSock: Variable Packets
Forgive me if this is an utterly newbie question: What''s the best way to handle variable packet size receipt in WinSock?
A previous post in another thread indicated that you could peek at the packet being received, and decide what to do based on it; is this a good way to handle variable sized packets?
By variable sized, I mean the following:
typedef struct _Velocity
{
DWORD dwType;
DWORD dwSize;
float X;
float Y;
float Z;
} Velocity;
typedef struct _TextMessage
{
DWORD dwSize;
DWORD dwType;
char szMessage[128];
DWORD dwColor;
}
Obviously I don''t want to pad each structure with extra bytes so that I can handle each packet the "easy way"... what about sending a ''type packet'' to the server that indicates the next received packet''s type will be?
MatrixCubed
Good idea MatrixCubed! Maybe it''s good to send a WORD for type and a WORD for size. Together they make a nice DWORD...
But sometimes you need the size&type in combination with the rest of the packet, somewhere in a function.
I don''t know if it works, but what do you think of a C++ approach:
But sometimes you need the size&type in combination with the rest of the packet, somewhere in a function.
I don''t know if it works, but what do you think of a C++ approach:
class CPacket{ WORD wSize; WORD wType;};class CPacketTime : public CPacket{ FILETIME Time;};class CPacketName : public CPacket{ char szName[32];};
![](http://www.baskuenen.myweb.nl/images/title.jpg)
I handle packets sizes using predefined size table known both by the server and client, however i''ve found this way to be too resritctive. I suggest going with the type/size header, it''s more robust, as any future server can talk to any old client, though the new packets would be unprocessable ofcourse. The way i have it now i have to recompile a new client and server every time i change the packet size table or add a new packet type. I suggest using 2 bytes each for type and size, you don''t need a DWORD worth of header and types. Good Luck.
-ddn
-ddn
Heh, well it''s not really the answer I was looking for
I want to know how to handle reading/recv()()''ing different data-structures, assuming all structures have common fields (let''s assume WORD wType and WORD wSize).
Should I use recv() to ''peek'' (not read) a data-structure''s type, then read it into a buffer which is cast/memcpy''d to the correct structure? Should I attempt to send multiple packets, the first indicating the type, the second representing the actual data? (This way, I think both would need an ID right?)
I think I''m missing something important with all this; I might just wait to get my Network Programming in Windows book.![](wink.gif)
MatrixCubed
![](smile.gif)
Should I use recv() to ''peek'' (not read) a data-structure''s type, then read it into a buffer which is cast/memcpy''d to the correct structure? Should I attempt to send multiple packets, the first indicating the type, the second representing the actual data? (This way, I think both would need an ID right?)
I think I''m missing something important with all this; I might just wait to get my Network Programming in Windows book.
![](wink.gif)
MatrixCubed
Here''s how I''ve seen it done, although this is perhaps not "the best" way, heh.
Basically, each client is assigned a text buffer of a pretty big size (something like 2k) which packets are read into. Each packet starts out with a "command byte" which specifies which packet it is (randomly making up numbers here) say 0x01 for logging in, 0x02 for creating new player, etc. Next comes two bytes (a DWORD I guess, I always forget how big a WORD and DWORD are
which contain the size of the data FOLLOWING these two bytes, ie. the rest of the packet. So, a routine then just reads this much data into the socket''s buffer, and then when a function requires that data, it just pulls it out of the buffer rather than a predefined structure for each packet.
What is at each byte of the buffer is simply documented in a file somewhere. For example, the "login packet" might look like
BYTE command (0x01)
DWORD length (0xff)
char username[128]
char password[128]
or maybe
BYTE command (0x12) (move)
DWORD length 0x0f
BYTE direction
BYTE running (are we running or walking?)
and the buffer is just some char array like buffer[256]
so, looking at the documentation, you can tell that buffer[0] through buffer[128] will contain their username, and 129-255 will be their password. Or, in the second example, buffer[0] is the direction to move in, and buffer[1] is whether they are walking or running.
Does this make *any* sense? Cause I tend not to
It might not be as easy to read as having a different structure for each possible packet, but if you''re in a game that can have over one hundred packets (like an online rpg, my area of study
, then that could translate into a TON of structures to maintain, and a really big switch() statement saying
case move: readIntoMovementStructure
case login: readIntoLoginStructure
rather than just going by how long it says the packet is and using that.
Hope that helped![](smile.gif)
Anthracks
Basically, each client is assigned a text buffer of a pretty big size (something like 2k) which packets are read into. Each packet starts out with a "command byte" which specifies which packet it is (randomly making up numbers here) say 0x01 for logging in, 0x02 for creating new player, etc. Next comes two bytes (a DWORD I guess, I always forget how big a WORD and DWORD are
![](wink.gif)
What is at each byte of the buffer is simply documented in a file somewhere. For example, the "login packet" might look like
BYTE command (0x01)
DWORD length (0xff)
char username[128]
char password[128]
or maybe
BYTE command (0x12) (move)
DWORD length 0x0f
BYTE direction
BYTE running (are we running or walking?)
and the buffer is just some char array like buffer[256]
so, looking at the documentation, you can tell that buffer[0] through buffer[128] will contain their username, and 129-255 will be their password. Or, in the second example, buffer[0] is the direction to move in, and buffer[1] is whether they are walking or running.
Does this make *any* sense? Cause I tend not to
![](smile.gif)
![](wink.gif)
case move: readIntoMovementStructure
case login: readIntoLoginStructure
rather than just going by how long it says the packet is and using that.
Hope that helped
![](smile.gif)
Anthracks
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement