1.BIG-ENDIAN、LITTLE-ENDIAN跟多字節類(lèi)型的數據有關(guān)的比如int,short,long型,而對單字節數據byte卻沒(méi)有影響。BIG-ENDIAN就是低位字節排放在內存的低端,高位字節排放在內存的高端。而LITTLE-ENDIAN正好相反。
比如 int a = 0x05060708
在BIG-ENDIAN的情況下存放為:
字節號 0 1 2 3
數據 05 06 07 08
在LITTLE-ENDIAN的情況下存放為:
字節號 0 1 2 3
數據 08 07 06 05
2.BIG-ENDIAN、LITTLE-ENDIAN、跟CPU有關(guān)的,每一種CPU不是BIG-ENDIAN就是LITTLE-ENDIAN、。IA架構的CPU中是Little-Endian,而PowerPC 、SPARC和Motorola處理器。這其實(shí)就是所謂的主機字節序。而網(wǎng)絡(luò )字節序是指數據在網(wǎng)絡(luò )上傳輸時(shí)是大頭還是小頭的,在Internet的網(wǎng)絡(luò )字節序是BIG-ENDIAN。所謂的JAVA字節序指的是在JAVA虛擬機中多字節類(lèi)型數據的存放順序,JAVA字節序也是BIG-ENDIAN。
3.所以在用C/C++寫(xiě)通信程序時(shí),在發(fā)送數據前務(wù)必用htonl和htons去把整型和短整型的數據進(jìn)行從主機字節序到網(wǎng)絡(luò )字節序的轉換,而接收數據后對于整型和短整型數據則必須調用ntohl和ntohs實(shí)現從網(wǎng)絡(luò )字節序到主機字節序的轉換。如果通信的一方是JAVA程序、一方是C/C++程序時(shí),則需要在C/C++一側使用以上幾個(gè)方法進(jìn)行字節序的轉換,而JAVA一側,則不需要做任何處理,因為JAVA字節序與網(wǎng)絡(luò )字節序都是BIG-ENDIAN,只要C/C++一側能正確進(jìn)行轉換即可(發(fā)送前從主機序到網(wǎng)絡(luò )序,接收時(shí)反變換)。如果通信的雙方都是JAVA,則根本不用考慮字節序的問(wèn)題了。
4.如果網(wǎng)絡(luò )上全部是PowerPC,SPARC和Motorola CPU的主機那么不會(huì )出現任何問(wèn)題,但由于實(shí)際存在大量的IA架構的CPU,所以經(jīng)常出現數據傳輸錯誤。
5.文章開(kāi)頭所提出的問(wèn)題,就是因為程序運行在X86架構的PC SERVER上,發(fā)送數據的一端用C實(shí)現的,接收一端是用JAVA實(shí)現的,而發(fā)送端在發(fā)送數據前未進(jìn)行從主機字節序到網(wǎng)絡(luò )字節序的轉換,這樣接收端接收到的是LITTLE-ENDIAN的數據,數據解釋自然出錯。
具體數據如下,實(shí)際發(fā)送的數據為23578
發(fā)送端發(fā)送數據: 1A 5C
接收端接收到數據后,按BIG-ENDIAN進(jìn)行解釋具體數據是多少?你們自己去計算并比較吧!
Big Endian and Little Endian
public class FormatTransfer {
/**
* 將int轉為低字節在前,高字節在后的byte數組
* @param n int
* @return byte[]
*/
public static byte[] toLH(int n) {
byte[] b = new byte[4];
b[0] = (byte) (n & 0xff);
b[1] = (byte) (n >> 8 & 0xff);
b[2] = (byte) (n >> 16 & 0xff);
b[3] = (byte) (n >> 24 & 0xff);
return b;
}
/**
* 將int轉為高字節在前,低字節在后的byte數組
* @param n int
* @return byte[]
*/
public static byte[] toHH(int n) {
byte[] b = new byte[4];
b[3] = (byte) (n & 0xff);
b[2] = (byte) (n >> 8 & 0xff);
b[1] = (byte) (n >> 16 & 0xff);
b[0] = (byte) (n >> 24 & 0xff);
return b;
}
/**
* 將short轉為低字節在前,高字節在后的byte數組
* @param n short
* @return byte[]
*/
public static byte[] toLH(short n) {
byte[] b = new byte[2];
b[0] = (byte) (n & 0xff);
b[1] = (byte) (n >> 8 & 0xff);
return b;
}
/**
* 將short轉為高字節在前,低字節在后的byte數組
* @param n short
* @return byte[]
*/
public static byte[] toHH(short n) {
byte[] b = new byte[2];
b[1] = (byte) (n & 0xff);
b[0] = (byte) (n >> 8 & 0xff);
return b;
}
/**
* 將將int轉為高字節在前,低字節在后的byte數組
public static byte[] toHH(int number) {
int temp = number;
byte[] b = new byte[4];
for (int i = b.length - 1; i > -1; i--) {
b = new Integer(temp & 0xff).byteValue();
temp = temp >> 8;
}
return b;
}
public static byte[] IntToByteArray(int i) {
byte[] abyte0 = new byte[4];
abyte0[3] = (byte) (0xff & i);
abyte0[2] = (byte) ((0xff00 & i) >> 8);
abyte0[1] = (byte) ((0xff0000 & i) >> 16);
abyte0[0] = (byte) ((0xff000000 & i) >> 24);
return abyte0;
}
*/
/**
* 將float轉為低字節在前,高字節在后的byte數組
*/
public static byte[] toLH(float f) {
return toLH(Float.floatToRawIntBits(f));
}
/**
* 將float轉為高字節在前,低字節在后的byte數組
*/
public static byte[] toHH(float f) {
return toHH(Float.floatToRawIntBits(f));
}
/**
* 將String轉為byte數組
*/
public static byte[] stringToBytes(String s, int length) {
while (s.getBytes().length < length) {
s += " ";
}
return s.getBytes();
}
/**
* 將字節數組轉換為String
* @param b byte[]
* @return String
*/
public static String bytesToString(byte[] b) {
StringBuffer result = new StringBuffer("");
int length = b.length;
for (int i=0; i<length; i++) {
result.append((char)(b & 0xff));
}
return result.toString();
}
/**
* 將字符串轉換為byte數組
* @param s String
* @return byte[]
*/
public static byte[] stringToBytes(String s) {
return s.getBytes();
}
/**
* 將高字節數組轉換為int
* @param b byte[]
* @return int
*/
public static int hBytesToInt(byte[] b) {
int s = 0;
for (int i = 0; i < 3; i++) {
if (b >= 0) {
s = s + b;
} else {
s = s + 256 + b;
}
s = s * 256;
}
if (b[3] >= 0) {
s = s + b[3];
} else {
s = s + 256 + b[3];
}
return s;
}
/**
* 將低字節數組轉換為int
* @param b byte[]
* @return int
*/
public static int lBytesToInt(byte[] b) {
int s = 0;
for (int i = 0; i < 3; i++) {
if (b[3-i] >= 0) {
s = s + b[3-i];
} else {
s = s + 256 + b[3-i];
}
s = s * 256;
}
if (b[0] >= 0) {
s = s + b[0];
} else {
s = s + 256 + b[0];
}
return s;
}
/**
* 高字節數組到short的轉換
* @param b byte[]
* @return short
*/
public static short hBytesToShort(byte[] b) {
int s = 0;
if (b[0] >= 0) {
s = s + b[0];
} else {
s = s + 256 + b[0];
}
s = s * 256;
if (b[1] >= 0) {
s = s + b[1];
} else {
s = s + 256 + b[1];
}
short result = (short)s;
return result;
}
/**
* 低字節數組到short的轉換
* @param b byte[]
* @return short
*/
public static short lBytesToShort(byte[] b) {
int s = 0;
if (b[1] >= 0) {
s = s + b[1];
} else {
s = s + 256 + b[1];
}
s = s * 256;
if (b[0] >= 0) {
s = s + b[0];
} else {
s = s + 256 + b[0];
}
short result = (short)s;
return result;
}
/**
* 高字節數組轉換為float
* @param b byte[]
* @return float
*/
public static float hBytesToFloat(byte[] b) {
int i = 0;
Float F = new Float(0.0);
i = ((((b[0]&0xff)<<8 | (b[1]&0xff))<<8) | (b[2]&0xff))<<8 | (b[3]&0xff);
return F.intBitsToFloat(i);
}
/**
* 低字節數組轉換為float
* @param b byte[]
* @return float
*/
public static float lBytesToFloat(byte[] b) {
int i = 0;
Float F = new Float(0.0);
i = ((((b[3]&0xff)<<8 | (b[2]&0xff))<<8) | (b[1]&0xff))<<8 | (b[0]&0xff);
return F.intBitsToFloat(i);
}
/**
* 將byte數組中的元素倒序排列
*/
public static byte[] bytesReverseOrder(byte[] b) {
int length = b.length;
byte[] result = new byte[length];
for(int i=0; i<length; i++) {
result[length-i-1] = b;
}
return result;
}
/**
* 打印byte數組
*/
public static void printBytes(byte[] bb) {
int length = bb.length;
for (int i=0; i<length; i++) {
System.out.print(bb + " ");
}
System.out.println("");
}
public static void logBytes(byte[] bb) {
int length = bb.length;
String ut = "";
for (int i=0; i<length; i++) {
ut = out + bb + " ";
}
}
/**
* 將int類(lèi)型的值轉換為字節序顛倒過(guò)來(lái)對應的int值
* @param i int
* @return int
*/
public static int reverseInt(int i) {
int result = FormatTransfer.hBytesToInt(FormatTransfer.toLH(i));
return result;
}
/**
* 將short類(lèi)型的值轉換為字節序顛倒過(guò)來(lái)對應的short值
* @param s short
* @return short
*/
public static short reverseShort(short s) {
short result = FormatTransfer.hBytesToShort(FormatTransfer.toLH(s));
return result;
}
/**
* 將float類(lèi)型的值轉換為字節序顛倒過(guò)來(lái)對應的float值
* @param f float
* @return float
*/
public static float reverseFloat(float f) {
float result = FormatTransfer.hBytesToFloat(FormatTransfer.toLH(f));
return result;
}
}
聯(lián)系客服