Advertisement

Structs over UDP

Started by January 21, 2005 01:26 PM
7 comments, last by GameDev.net 20 years ago
Happy Friday everybody!!! (sorry to those who are in different enough time zones to not be sharing in the same moment I am) I have a client/server system running over UDP using WinSock 2. Everything is working nicely when sending strings of data, but instead i would like to send a struct of bytes that contains client position information and the like. With the search function temporarily disabled, I've tried searching google and MSDN (perhaps not well enough) with no avail. Any techniques or information you can give me or direct me to are greatly appreciated. Thanks in advance, Jeff
you send it the same way as you send the string. i believe you just cast to (char *) and provide the appropriate size. been a while since i looked at my network code so the syntax escapes me. if you post your send code, I'll happily show you an example of sending a struct. just be sure that you limit the size of your struct such that it fits into a single UDP packet. UDP doesn't have guaranteed delivery so you want to avoid the case where your data is spread across multiple packets.

-me
Advertisement
hplus should add this to the faq or something. It seems to come up all the time.

Anyway...

send() and receive() take byte arrays, not strings. I know that they're prototyped to as char* but don't let that bother you - they'll send or receive whatever data you tell them too.

Palidine is right for the simple case. Just cast your struct pointer to a char*, give it the length of the struct, and you'll be fine.

In the fully general case it's a lot more complicated than that.

If you're just learning you might want to skip all the stuff below for now...

You may need to worry about endianness (if you have a 0x1234 should it be sent as 0x12 0x34 or as 0x34 0x12?). Windows does the latter but some other systems do the former. In particular many standard protocols explicity require the former. This is called "network byte order" and it's what htonl and it's friends is all about. If you only care about Windows and you're not trying to implement some industry standard protocol then you can ignore this problem.

You may have to worry about padding. If you have struct with a char followed by an int then you might think that the char is at offset 0 and the int at offset 1. However it often isn't unless you do some magic. In VC unless you tell it different the int will be at offset 4. Again, if you only care about some trivial learning program you can ignore this - at worst you waste a bit of bandwidth. However for a commerical app it's a bit different because now the worst case is that it's a security violation (those extra pad bytes might hold part of a password, they might contain a hidden vtable pointer which would give a hacker some insight into your memory layout, or something).

If your struct contains pointers and you want to send send the pointed-to data as well then you need to handle that. In case that isn't annoying enough you might also potentially have to send a self-referential structure (a circular list say) you need to be careful you don't go into an infinite loop. Similiarly you don't want to send a boatload more info then is necessary (consider a directed acyclic graph, if you just do a naive depth-first traveral you could end up sending the same data over and over again).

What character set are your strings in and how does the other side know? UTF-8 or UTF-16 are good choices but may require explicit conversion.

For the extra-pedantic out there or just those unfortunate enough to have to deal with obsolete or otherwise strange hardware not all machines use IEEE floats and you may have to do conversion.
-Mike
Thanks so much for the replies. I guess I really should have just tried sending a struct to see if it worked...and according to what I understand now, it should.

My game is currently only planned to run on Windows and my structs do not contain any pointers, so the padding discussion is basically what I should be looking at now. Efficient bandwidth usage is going to be of prime concern when i'm able to finish up some more of the preliminary graphics and get down to fixing up my server code to test with a few players.

In all, thanks again for your help. I hope to get a couple screenshots of this project up soon (if only my friend working on the artwork would move a bit more quickly).

Thanks,
Jeff
Btw: I did take the suggestion and add this to the Forum FAQ.
enum Bool { True, False, FileNotFound };
Quote:
Btw: I did take the suggestion and add this to the Forum FAQ.


I am so honored that something that I asked has become part of the FAQ that I have come to know and love. :)
Advertisement
example on how to send structs.

struct DATA{
Vector3 pos;
};

DATA send_data;

send(mySocket, (char*)&send_data, sizeof(DATA), 0);

then on the recv side you can do the same.

DATA recv_data;

recv(mySocket, (char*)&recv_data, sizeof(DATA), 0);
-[ thx ]-
Quote:
Original post by X5-Programmer
DATA send_data;

send(mySocket, (char*)&send_data, sizeof(DATA), 0);


Personally, I don't understand how that works. Wouldn't that just send the memory address of the data, and not the data itself?

This topic is closed to new replies.

Advertisement