假设已有写入的,不可更改的宿主程序,它通过socket接收这样的C ++结构:
#pragma pack(push, 2)
struct Data {
double x;
double y;
double z;
long frameNumber;
};
#pragma pack(pop)
platform:在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个可能的问题:
这些东西在Java中用C ++看起来是什么?
在几个小时内,我将提供“字节黑客”的精确样本数据(发送前的确切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
答案 0 :(得分:3)
假设已经编写了不可更改的宿主程序,它通过套接字
接收这样的C ++结构
然后你已经有一个主要的问题,一些不知名的人已经把你留作遗产了。您现在必须生成Java代码以符合特定C ++编译器对特定struct
的有线格式的概念,这取决于:
我强烈建议您利用这个机会修复整个megillah并为事务定义正确的 wire 格式。
完成后,您可以使用DataOutputStream
的设施轻松地模拟它,或者如果问题更严重并且涉及到字节序,则NIO加ByteBuffer.
答案 1 :(得分: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();
}
使用ByteBufer和putDouble()/ putInt()。
答案 2 :(得分:1)
您需要在服务器平台上验证用于double(通常是IEEE标准,但不一定是)以及long(big vs little endian)的编码。您还需要识别所涉及的任何填充。
然后,如果它们不是java本机编码,则需要手动构造适合发送的二进制值。这可能是非常重要的,特别是对于浮点值,如果你在一个相当混乱的服务器平台上。
此外,追踪那些决定对您无法更改的服务器使用隐式二进制协议的人,并使用橡胶软管密码分析:
http://en.wikipedia.org/wiki/Rubber-hose_cryptanalysis
在不了解服务器平台的所有细节的情况下,没有简单的方法。
Java在所有平台上都有浮点数和整数的标准表示,但c ++没有定义这些东西。它是针对c ++的平台/体系结构。