如何通过套接字发送与c++兼容的Java结构体
How to send by socket C++ compatible struct from Java?
假设已经编写了一个不可更改的宿主程序,通过套接字接收这样的c++结构体:
#pragma pack(push, 2)
struct Data {
double x;
double y;
double z;
long frameNumber;
};
#pragma pack(pop)
平台: c++/32位Windows应用程序编译在Visual Studio 2008
如何从Java Socket发送这样的数据?我试图用putDouble()和putLong()填充ByteBuffer,也假设putInt()为32位,但我无法产生有效值。
我也随机生成和发送数据,并且结构级字节分配看起来很好(我只能随机化一个值,例如X),但是我不能生成精确的值(可能是不同的双精度表示?),而只能通过发送Math.random() * double . max_value;
我可以使用谷歌协议缓冲区只在一方(客户端生产数据)来解决这个问题吗?
请记住,我不能更改服务器(接收)端
我知道我可以将发送数据移动到c++并使用JNI,但我正在寻找更简单的解决方案。
我看到这里至少有两个可能的问题:
- 字节级双表示(如另一侧的01234567和76543210)
- 位表示为一个字节(如00000001和1000000在另一边)
这些东西在Java和c++中是什么样子的?
在几个小时内,我将为"字节破解"提供精确的示例数据(发送前的精确Java值和c++中接收的double值)
关于服务器不良设计应答
我知道这样的实现和不可更改的服务器是坏软件,但在这个问题中的环境是注入一些数据到小的老应用程序在"业余水平"
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
假设已经有一个写好的、不可改变的宿主程序,通过套接字
接收这样的c++结构体
那么你已经有一个重大问题,某个不知名的人好心地给你留下了遗产。您现在必须生成Java代码,以符合特定的c++编译器对特定struct
的连线格式的概念,这取决于:
- 件>
- 编译器供应商
- 编译器版本
- 编译选项
- 周围的#pragmas
- …
我强烈建议您抓住机会修复整个兆拉,并为交易定义一个适当的电线格式。
一旦你做到了这一点,你就可以很容易地用DataOutputStream
的工具来模拟它,或者如果问题更糟,涉及到端序,NIO加ByteBuffer.
我明白了。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();
}
和putDouble()/putInt()使用bytebuffer
您需要与服务器在平台上验证用于双端(通常是IEEE标准,但不一定是)和长端(大端对小端)的编码。您还需要确定所涉及的填充。
如果它们不是java原生编码,则需要手动构造适合发送的二进制值。如果您在一个非常混乱的服务器平台上,这可能是非常重要的,特别是对于浮点值。
还有,找到那个决定在你无法更改的服务器上使用隐式二进制协议的人,并对他们使用橡皮软管密码分析:
http://en.wikipedia.org/wiki/Rubber-hose_cryptanalysis如果不知道服务器平台的所有细节,这是不容易做到的。
Java在所有平台上都有浮点数和整型数的标准表示,但c++没有定义这些东西。
- 根据用户回答声明"Players"。用户选择玩家数量。播放器是结构体
- 结构体 S { int align; } 之间的区别;(struct 关键字后的名称)和 struct { int al
- C++ - 如何在结构向量中找到结构体一个成员的最大值?
- 包含 std::list 的结构体的 C++ 初始化
- 结构体和类的不同大小(),彼此具有相同的字段类型
- 如何使用结构体的向量数组?
- 如何使用结构体在C++中更改这些代码?
- 无法在 Mosquitto MQTT Broker 插件上访问结构体 mosquitto 的元素
- 我应该如何在C++中使用结构体解决输入失败的问题?
- Qsort() 比较结构体整数的总和
- 如何使用迭代器指向结构体c++的向量
- 在C++中使用链表的堆栈实现中,访问结构体headNode成员count和top会导致运行时错误
- 如何获取结构体成员的地址
- 创建结构体向量,表达式:向量下标超出范围
- boost::任何带有结构体和无符号整数
- 如何在构造函数中初始化结构体的动态数组?
- 只写结构体的某些字段
- C++ push_back() 一个结构体到一个向量中
- C++14 结构体上的统一初始化
- 如何通过套接字发送与c++兼容的Java结构体