How to send a socket with a C ++ compatible structure from Java?

Suppose you have already written an immutable host program that receives the following C ++ socket structure:

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

platform: C ++ / 32-bit Windows application compiled in Visual Studio 2008

How to send such data from Java Socket? I tried to populate a ByteBuffer with putDouble () and putLong (), also putInt (), assuming it lasts 32 bits, but I cannot give valid values.

I also generated and sent data randomly, and the byte assignment at the structure level looked fine (I can randomly select only one value, for example X), but I cannot get the exact value (maybe another double representation?), But only random stuff by sending Math.random () * Double.MAX_VALUE;

Can I use Google protocol buffers on one side only (client data) to solve this problem?

remember, I can not change the server side (recipient)

I know that I can move data sending in C ++ and use JNI, but I'm looking for a simpler solution.

I see at least 2 possible problems here:

  • double representation at the byte level (e.g. 01234567 and 76543210 on the other hand).
  • a bit in one byte (e.g. 00000001 and 1,000,000 on the other hand)

What do these things look like in Java in C ++?

In a few hours I will give the exact sample data for a “byte hack” (the exact Java value before sending and the value of the resulting double in C ++)

About bad-design server answers

I know that such an implemented and immutable server is poor software, but the environment in this problem is to enter some data into a small old application at the "hobbistic-level" level

Java representation

Maybe this will help some bit C ++ expert:

 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 
+6
source share
3 answers

I get it. The Int value is sent in a fine (it may not be able to verify this 100% confidence in the host program), the problem is the double endian. You need to convert the doubles before sending:

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

And use ByteBufer with putDouble () / putInt ().

+3
source

Suppose that an immutable host program has already been written that receives such a C ++ structure through a socket

Then you already have a serious problem that an unknown person has kindly left for you as a legacy. Now you need to create Java code to match the specific concept of the C ++ compiler wire format of a particular struct , which depends on:

  • Hardware
  • compiler provider
  • compiler version
  • compilation options
  • surrounding #pragmas
  • ...

I highly recommend that you take the opportunity to fix the entire megaligue and determine the correct transaction format for the transaction.

After you have done this, you can easily emulate it using the DataOutputStream tools, or if the problem is even worse and matters endial-ness, NIO plus ByteBuffer.

+3
source

You will need to check the encoding used for double (usually this is the IEEE standard, but this is not necessary), as well as long (large or small) on the platform with the server. You will also need to indicate whether the add-on will also be added.

Then you need to manually build the binary values ​​suitable for sending if they are not native java encodings. This can be nontrivial, especially for floating point values, if you are on a rather confusing server platform.

In addition, track down the person who decided to use the implicit binary protocol for the server that you cannot change, and use the rubber hose cryptanalysis on them:

http://en.wikipedia.org/wiki/Rubber-hose_cryptanalysis

There is no easy way to do this without knowing all the details about the server platform.

Java has a standard representation for float and int on all platforms, but C ++ does not define these things. This is a C ++ specific platform / architecture.

+1
source

Source: https://habr.com/ru/post/944849/


All Articles