Data conversion during Java and C/C ++ Network Communication
Recently, an Android application needs to transmit data with the PC end through socket. The PC end is developed in C ++. To facilitate transmission, data is converted into byte arrays before being sent. I thought everything was fine, but there were still some problems in the process. The following are some of my problems and solutions. Here is a simple record, and I hope you can solve them quickly. At the same time, you are welcome to make corrections ~
Receiving and sending of Java Socket
First, we will establish a socket connection and obtain InputStream and OutputStream from it. When receiving, I use a DataInputStream to package InputStream of the Socket, so that the data types of different sizes can be received later. During sending, The OutputStream () is encapsulated through DataOutputStream (), and different data types are written. Then, ByteArrayOutputStream is packaged into word throttling, which is sent through the established Socket channel. In this way, there are two problems.
Question 1: size issues
PC devices use the x86 platform and the data is in the small-end format. The jvm virtual machine uses a large-end format. When you use Java to read a byte, such as calling dataInputStream. read (), you can normally read a byte. However, if you want to read multi-byte data types, such as dataInputStream. readInt (), a data error occurs. The small-end format stores low-byte data in the low-address storage space, while the large-end format stores low-byte data in the high-address space. In this way, the data's high position has been reversed.
Solution
The solution to this problem is also relatively easy. The results can be obtained by performing a butterfly switch on the high status of the error data. You can perform short-based conversion for the size-side format conversion, and then call the short conversion for the Int Data's high and low bits. The Code is as follows:
/*** Size-end butterfly swap ** @ param data * short data to be exchanged * @ return number of short converted */private static short swapShortToLittleEndian (short data) {short ret = (short) (data <8) | (data> 8) & 0x00FF); ret = (short) (ret & 0 xFFFF ); return ret ;}
Then, the int data can be converted to the upper/lower 16 bits:
/*** Size-end butterfly swap ** @ param data * int data to be exchanged * @ return number of int converted */private static void swapIntToLittleEndian (int data) {int ret = swapShortToLittleEndian (short) (data> 16) & 0 xFFFF) | (swapShortToLittleEndian (short) data) <16); return ret ;}
The above two functions can convert 16-byte and 32-byte data into a small-end format. The same principle can be used for 64-bit data.
PS: Some friends may have some doubts about the frequent and 0 xFFFF/0xFF operations. This is also the second problem to be mentioned. This is necessary for the operation. The reason is as follows:
Question 2: implicit type conversion in Java
In Java, +-*/>>>><<<<<| ^ (addition, subtraction, multiplication, division, right shift, left shift, unsigned right shift, bitwise AND, bitwise OR, bitwise exclusive or) operations will first convert byte to int and then perform operations. Then, this process may cause many problems.
Solution
We all know that in Java, only the number of symbols exists to facilitate data processing. That is, the highest bit is used to represent the symbol, and the other bit is used to represent the actual data. In the above size-end conversion, we need to first move the low 8-bit data to the high 8-bit data, while moving the high 8-bit data to the low 8-bit data. In the left shift process, there is no doubt that the right side is automatically filled with 0, so the result of direct shift will be what we want. However, if it is a right shift, the correct result can also be obtained for a positive number (the highest bit is 0); however, if it is a negative number (the highest bit is 1 ), at this time, when the right shift is performed, the high position is automatically supplemented by 1. Of course, this can be solved by the operator ">>>", but there is another problem:When a byte is shifted, the system implicitly converts it into int data. If it is a negative number, the complete high data is 1..
If the bitwise AND operation is not performed with 0xFF after the right shift, the subsequent and high data bits or the high position will be directly set to 1, which is why frequent bitwise AND operation are performed.
To sum up:
1. When receiving C ++ unsigned data using Java, you must pay attention to the conversion of the size end.
2. In addition, if you encounter a shift operation, you must clear the high position after the right shift to eliminate the error.
The above are my own problems and solutions. If you have more solutions, please add them!