Java ByteBuffer - > [NSData bytes]到UInt16

时间:2014-06-08 11:59:15

标签: java objective-c sockets nsdata memcpy

大家好日子。

我正在编写基于套接字的客户端 - 服务器应用程序。服务器是用Java,客户端编写的 - 在iOS SDK 7上使用Objective-C。

我的服务器使用下一个代码将数据写入连接的套接字:

//Socket client = new ...;
DataOutputStream out = new DataOutputStream(client.getOutputStream());
// send package
String message = "pings"; // package body
byte bodySize = (byte) message.length();
java.nio.ByteBuffer buffer = java.nio.ByteBuffer.allocate(2 + 2 + 1 + bodySize);
buffer.putShort((short) 16); // package ID (2 bytes)
buffer.putShort((short) 7); // package header (2 bytes, bitmask options)
buffer.put(bodySize); // calculate & put body size in 5th byte (1 byte)
buffer.put(message.getBytes()); // put the message to buffer (+5 bytes)

out.write(buffer.array()); // write to stream
out.close(); // close stream

然后我试图在Objective-C客户端中解析接受的NSData。这是代码:

- (UInt16)packageIdFromPackageHead:(NSData *)data {
    const void *bytes = [data bytes];
    UInt16 packageId;
    memcpy(&packageId, bytes + 0, 2); // get first 2 bytes, it must be short = 16
    return packageId;
}

但是,在" packageId"变量我有值" 4096"。这是什么?我的16位十进制值在哪里?

接下来,我试图获取下一个值,"包标题"。我写了以下代码:

UInt16 header;
memcpy(&header, bytes + 2, 2); // skip first 2 bytes, copy next 2 bytes, must be short = 7

我得到了巨大的价值,1792年。为什么?这个数字是什么意思?我尝试了几个补偿,+ 2,+ 3 - 没什么。我无法获得正确的价值。我尝试使用一些转换

header = CFSwapInt32BigToHost(header);

header = CFSwapInt32HostToBig(header);

这没有任何结果 - 每次转换后我都得到0。

接下来,当我试图获得第5个字节时(它包含我们的消息字符串长度,你还记得)。这是代码:

UInt8 bodySize;
memcpy(&bodySize, bytes + 4, 1); // get the 5th byte

我得到了值

'\x05'

这是正确的。

我几乎可以肯定输入的NSData *值是正确的。在这里,您可以看到Xcode的内存转储屏幕截图:

Debug mode. Input NSData * memory dump

哪里有问题?在服务器代码中?或者在我的客户端阅读代码?请帮助,我花了两天时间找到解决方案,但我仍然无法得到它。

1 个答案:

答案 0 :(得分:0)

感谢Hot Licks!

正确的客户代码是:

const void *bytes = [data bytes];
UInt16 packageId; // 16-bit value
memcpy(&packageId, bytes + 0, 2); // copy first 2 bytes
packageId = CFSwapInt16BigToHost(packageId); // fix endianness for 16-bit value
return packageId; // now we got correct value

或者,更方便的是,使用以下命令修改服务器上的Java代码:

java.nio.ByteBuffer buffer = java.nio.ByteBuffer.allocate(2 + 2 + 1 + bodySize);
buffer.order(java.nio.ByteOrder.LITTLE_ENDIAN);

在此修改之后,初始客户端代码将正常工作,而无需使用CFSwapInt ...函数。

非常感谢你的帮助!