Jump to content
  • Advertisement
Sign in to follow this  
polyfrag

Sending float Windows <-> Linux

This topic is 2356 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

[color=#000000][font=verdana, arial, sans-serif]

I send a float equal to 4.000 from Windows to an Amazon EC2 Linux server, but the server reads it as 8.47522e+11.[/font]
[color=#000000][font=verdana, arial, sans-serif]

The server sends back 4.000 but Windows reads it as 0.0.[/font]
[color=#000000][font=verdana, arial, sans-serif]

I tried changing the byte order using this on Windows:[/font]

[color=#000000][font=verdana, arial, sans-serif]

[background=rgb(242, 242, 242)]void ReverseFloat(float* f)
{
unsigned char* uc = (unsigned char*)f;
unsigned char temp = uc[0];
uc[0] = uc[3];
uc[3] = temp;
temp = uc[1];
uc[1] = uc[2];
uc[2] = temp;
}
[/background][/font]

[color=#000000][font=verdana, arial, sans-serif]

But the server now gets 8.47518e+11 and Windows gets 0.0.[/font]
[color=#000000][font=verdana, arial, sans-serif]

The struct is packed and it still gives me the wrong result.[/font]

[color=#000000][font=verdana, arial, sans-serif]

[background=rgb(242, 242, 242)]#if !defined( _SERVER )
#pragma pack(push, 1)
#endif
typedef struct
{
unsigned char type;
float version;
char username[16];
char password[16];
}
#if defined( _SERVER )
__attribute__ ((packed))
#endif
LoginPacket;
#if !defined( _SERVER )
#pragma pack(pop)
#endif
[/background][/font]

The client sends 37 bytes and server receives 37 bytes.

The server sends back this:

#if !defined( _SERVER )
#pragma pack(push, 1)
#endif
typedef struct
{
unsigned char type;
float version;
}
#if defined( _SERVER )
__attribute__ ((packed))
#endif
WrongVersionPacket;
#if !defined( _SERVER )
#pragma pack(pop)
#endif


The server says it sends 8 bytes for some reason and the client receives 8. I don't know why it's 8... should be 5. Is a float 7 bytes on Amazon Linux? Edited by polyfrag

Share this post


Link to post
Share on other sites
Advertisement
You might try checking what is the standard used by the compilers on both systems. Although I'd not use floating point for data that is sent over the network. It's a can of worms in general. It's better to send the floating point as a string or send fixed a point number, if it isn't vital to send a floating point number. If you specifically need to send floating point numbers, it might be better to use protobuf or some other library that handles the differences internally.

Share this post


Link to post
Share on other sites
Your problem is probably in the struct packing of the different compilers, not in the byte representation of the floats. In fact, I think your pack push/pop is causing the problem, because GCC doesn't care about those directives.
Most EC2 servers and most Windows machines use the x86 or x86/64 hardware platform, which encodes floats the same -- as IEEE-753 4-byte little-endian values.

The easiest way to make structs largely the same across compilers is to sort your data members from largest natural alignment to smallest -- first double, then int64, then pointer, then size_t, then float, then int, then short, then char.
If you don't want to re-order the struct members, then the second option is to go through a marshalling/de-marshalling library, rather than doing straight byte copies.

Share this post


Link to post
Share on other sites
Seconding the marshaling system.

The x86 platform is one of the few that allows mismatched alignment of integers and floats. Most other systems will crash on misaligned data. Even the x86 stopped supporting misaligned data with the newer extended data types; anything after '95 such as the 128-bit packed types.

A marshaling system will ensure that you don't violate alignment constraints which could crash your app. Edited by frob

Share this post


Link to post
Share on other sites
I'd treat sending data through a network the same way as storing data in files, i.e. don't trust anything about whoever else may end up accessing the data, only process raw unsigned bytes and nothing else, and use that as a basis for other types (larger integers, floating point, strings, etc.).

Share this post


Link to post
Share on other sites

There is no wide char in your struct; it has nothing to do with the problem as posted.

It's using 4 bytes per char like in Java

Share this post


Link to post
Share on other sites
That is incorrect. The char is still only 1 byte. There are 3 bytes of padding due to struct alignment for the following member (the float).

Put 4 chars in a struct all by themselves and your struct will only be 4 bytes in size. Edited by Nypyren

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!