Good day to all.
I'm writing a client-server application based on sockets. Server is written with Java, client - with Objective-C on iOS SDK 7.
My server writes data to a connected socket with the next code:
//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
Then I'm trying to parse accepted NSData in Objective-C client. Here's the code:
- (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;
}
But, in the "packageId" variable I have the value "4096". What is this? Where is my 16 decimal value?
Next, I'm trying to get the next value, "package header". I wrote the following code:
UInt16 header;
memcpy(&header, bytes + 2, 2); // skip first 2 bytes, copy next 2 bytes, must be short = 7
I got a huge value, 1792. Why? What is this number means? I tried several offsets, +2, +3 - nothing. I can't get a correct value. I tried to use some conversion as
header = CFSwapInt32BigToHost(header);
or
header = CFSwapInt32HostToBig(header);
This leads to nothing - I got 0 every time after conversion.
Next, when I tried to get the 5th byte (it contains our message string length, you remember). Here's the code:
UInt8 bodySize;
memcpy(&bodySize, bytes + 4, 1); // get the 5th byte
I got the value
'\x05'
And it is correct.
I'm almost certain that the input NSData * value is correct. Here you can see the memory dump screenshot from Xcode:
Debug mode. Input NSData * memory dump
Where is a problem? In the server code? Or in my client reading code? Please help, I spent 2 days to find a solution and I still couldn't get it.
Thanks to Hot Licks!
Correct client code is:
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
Or, and it's more convenient, modify Java code on the server with:
java.nio.ByteBuffer buffer = java.nio.ByteBuffer.allocate(2 + 2 + 1 + bodySize);
buffer.order(java.nio.ByteOrder.LITTLE_ENDIAN);
After this modification the initial client code will work correctly without using CFSwapInt... functions.
Many-many thanks for your help!