Archived

This topic is now archived and is closed to further replies.

how does microsoft do this?

This topic is 5533 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

microsoft''s direct x direct play 8 allows you to send a structure as your data, how do they do that? --Fireking Owner/Leader Genetics 3rd Dimension Development

Share this post


Link to post
Share on other sites
I''m doing the same thing with just winsock 1.1. Its really easy, just have your struct, then when you send it just send like this:

send(sock, (char *)mystruct1 ...)

then on your recv just cast it into an identical struct

mystruct struct1;
recv(sock, (char *)mystruct1 ...)
and you then can send a struct

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Sending structs that was is kind of icky, and won''t work if you want to make your program portable.

Structs are usually padded and aligned by compiliers, so their size and alignment is not always what you would expect.

For example:

struct X
{
char a;
int b;
};

Might have a different size depending on the platform and compilier used. Generally sizes are rounded to the nearest power or multiple of 2.

So sizeof(X) might be 5 on some systems, or 8 on others.

Also sending structs this way won''t work at all if one system is little endian and the other is big endian. You would be better off using some sort of Pack/Unpack method for each struct you want to use, making use of the ntoh* and hton* functions.

E.g.
void PackX(X x, void *buffer)
{
*((char *)(buffer)) = x.a;
*((int*)(buffer + 1)) = htonl(x.b);
}

void UnpackX(X &x, void *buffer)
{
x.a = *(char *)(buffer);
x.b = ntohl( *((int *)(buffer + 1));
}

So you would pack your struct before you send it, and unpack it after your received it.

E.g.

X x;
char message[SIZE];
PackX(x, message);
send(message):

and

X x;
char message[SIZE];
recv(message):
UnpackX(x, message);

Share this post


Link to post
Share on other sites
quote:
Original post by Anonymous Poster
Structs are usually padded and aligned by compiliers, so their size and alignment is not always what you would expect.



one would assume that since he''s writing the program sending data,
there''s a really good chance he''s also writing the program that
recieves it.. since structs are usually custom.
and based on that fact, one would assume that he''s compiling
using the same compiler and platform.
and based on that fact, the alignment and padding should
always be what he expects, right?

-eldee
;another space monkey;
[ Forced Evolution Studios ]


::evolve::

''In C we had to code our own bugs. In C++ we can inherit them.''

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
unless the server runs on linux compiled with gcc and the client runs on win32 compiled with vis c++.....

Share this post


Link to post
Share on other sites
I think the AP was just pointing these things out for future reference, incase he does deside to run a server on a different platform/compiler... I''m sure you''ll agree its better to have all the infomation to begin with rather than half the infomation and wonder why it doesnt work later?

Personaly, I think a pack/unpack function is a very good idea, as it would allow you to save the amount of data being sent, for example if you had a number which could only used a max of 24 bits, and 8 bool values, you could back them all into one 32bit buffer and send, instead of hoping the underlieing stack/API might work some magic for u
(can you tell I''ve been coding the HL SDK recently? hehe)

Share this post


Link to post
Share on other sites
(FYI I''m the Anon poster who put the packed stuff there)

The solution linked to by Sneftel (turning off padding) will not work in all cases so it isn''t the best solution. Padding will not solve endian issues.

There is a reason that structs are padded by the compilier: to optimize access to data members.

Without padding, each access to the struct could entail a performance hit, (extra instructions, etc.). Since sending over the network is already a slow operation the extra effort of packing/unpacking isn''t much of an impace. However, the extra instructions required to access unpadded data, especially in a tight inner loop, could cause a noticible performace loss. (Probably not, but it could).

Now, if you are just learning about networking, then you can worry about this stuff later. Also, if you never intend to port to a different CPU architecture, you can use the Sneftel''s solution.

Share this post


Link to post
Share on other sites
quote:
Original post by Xiol
However, the extra instructions required to access unpadded data, especially in a tight inner loop, could cause a noticible performace loss. (Probably not, but it could).



You could have two structures with the same data but one is padded and the other isn''t. When you receive the unpadded struct, you copy all members into the padded one and use it for all your operations.

Share this post


Link to post
Share on other sites
quote:
Original post by Prosper/LOADED
You could have two structures with the same data but one is padded and the other isn''t. When you receive the unpadded struct, you copy all members into the padded one and use it for all your operations.


Of course, how is that any different to the pack/unpack method?

If I had my way, I''d have all of you shot!


codeka.com - Just click it.

Share this post


Link to post
Share on other sites
Sending structs over a streaming protocol like TCP is a bad idea. There''s no guarantee that you''ll get the whole struct with one call to recv().

Share this post


Link to post
Share on other sites
You can either memcpy your struct to an array of chars and send that or cast your struct as an array of chars. It''s the same thing.

You should, however, never RECV to a struct or if you really want to, RECV to a temporary struct (it makes checking the header a little easier) and copy it to an array of chars. Otherwise you''re shooting yourself in the foot when you go to see if you have the whole message or two or more messages in one packet. You need to recieve to an array of chars and then do some checking before you memcpy the char buffer into the struct.

With my Winsock class I have a message class that handles all of this so when I call GetMessage() it will only return a message struct if there''s a complete message available. Then I just keep calling GetMessage() until it doesn''t return a message.

The method sets the message.type to -1 of there''s not a message available. There are a couple other negative numbers it''ll return for checking why it didn''t return a message. Those were just for debugging though.

Ben


IcarusIndie.com [ The Rabbit Hole | The Labyrinth | DevZone | Gang Wars | The Wall | Hosting | Tiberian Merchandise!!!! | GameShot ]

Share this post


Link to post
Share on other sites