如何从Java发送socket C++兼容结构?

Pio*_*ler 6 c++ java sockets double struct

假设已经编写了不可更改的宿主程序,它通过socket接收这样的C++结构:

#pragma pack(push, 2)
struct Data {
  double x;
  double y;
  double z;
  long frameNumber;
};
#pragma pack(pop) 
Run Code Online (Sandbox Code Playgroud)

平台:在Visual Studio 2008中编译的C++/32位Windows应用程序

如何从Java Socket发送这样的数据?我已经注意用putDouble()填充ByteBuffer,putLong(),putInt()假设长达32位,但我无法生成有效值.

我也随机生成和发送数据,并且结构级别的字节赋值看起来很好(我只能随机化一个值,例如X),但我不能产生精确的值(可能是不同的双重表示?),而只是通过发送随机的东西Math.random()*Double.MAX_VALUE;

我是否可以仅在一方(产生数据的客户端)上使用Google Protocol Buffers来解决此问题?

记住,我无法改变服务器(接收)方面

我知道我可以将数据发送到C++并使用JNI,但我正在寻找更简单的解决方案.

我在这里看到至少2个可能的问题:

  • 字节级的双重表示(如01234567和另一侧的76543210)
  • 一个字节中的位表示(如00000001和另一侧的1000000)

这些东西在C++中用Java看起来是什么样的?

几个小时后,我将提供"字节黑客"的精确样本数据(发送前的确切Java值和C++中收到的double的值)

关于服务器坏设计回答

我知道这样的实现和不可更改的服务器是坏软件,但这个问题的环境是在"hobbistic-level"向小型旧应用程序注入一些数据

Java表示

也许这会对某些位级C++专家有所帮助:

Long.toBinaryString( Double.doubleToRawLongBits( (double) 0 ) );
// 000000000000000000000000000000000000000000000000000000000000000

Long.toBinaryString( Double.doubleToRawLongBits( 1 ) );
// 011111111110000000000000000000000000000000000000000000000000000

Long.toBinaryString( Double.doubleToRawLongBits( 1.1 ) );
// 011111111110001100110011001100110011001100110011001100110011010

Long.toBinaryString( Double.doubleToRawLongBits( 1024 ) );
// 100000010010000000000000000000000000000000000000000000000000000

Long.toBinaryString( Double.doubleToRawLongBits( 1024.1024 ) );
// 100000010010000000000000110100011011011100010111010110001110001

Long.toBinaryString( Double.doubleToRawLongBits( Double.MAX_VALUE ) );
// 111111111101111111111111111111111111111111111111111111111111111
Run Code Online (Sandbox Code Playgroud)

Pio*_*ler 3

我想到了。Int 值发送得很好(可能无法在主机程序中 100% 确定地检查这一点),问题出在双字节字节序上。您需要在发送之前转换双精度数:

public static double changeEndian( double x ) {
      ByteBuffer cv = ByteBuffer.allocate( 8 ).putDouble( x );
      cv.order( ByteOrder.LITTLE_ENDIAN );
      cv.rewind();
      return cv.getDouble();
}
Run Code Online (Sandbox Code Playgroud)

并将 ByteBufer 与 putDouble()/putInt() 一起使用。