主机字节序 与 网络字节序

Posted 风来了

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了主机字节序 与 网络字节序相关的知识,希望对你有一定的参考价值。

一、字节顺序

是指占用内存多于一个字节类型的数据在内存中的存放顺序。


计算机电路先处理低位字节,效率比较高,因为计算都是从低位开始的。所以,计算机的内部处理都是小端字节序。

但是,网络传输、文件储存、人类读写习惯使用大端字节序。

  java中一个int型数据占用4个字节,假如有一个16进制的int数,int value =(高字节) 0x01020304 (低字节)

小端字节序(little endian):低字节数据存放在内存低地址

大端字节序(bigendian): 低字节数据存放在高地址处

 

主机字节序跟CPU有关的,IA架构(Intel、AMD)的CPU中是Little-Endian

所谓的JAVA字节序指的是在JAVA虚拟机中多字节类型数据的存放顺序,JAVA字节序也是BIG-ENDIAN。

由于JVM会根据底层的操作系统和CPU自动进行字节序的转换,

所以我们使用java进行网络编程,几乎感觉不到字节序的存在。

  

二、ByteBuffer 示例

public static void byteOrder() {

        int x = 0x01020304;

        ByteBuffer bb = ByteBuffer.wrap(new byte[4]);
        bb.asIntBuffer().put(x);
        System.out.println( bb.order() +  " 内存数据 " +  Arrays.toString(bb.array()));

        bb.order(ByteOrder.LITTLE_ENDIAN);
        bb.asIntBuffer().put(x);
        System.out.println( bb.order() +    " 内存数据 " +  Arrays.toString(bb.array()));
    }

BIG_ENDIAN 内存数据 [1, 2, 3, 4]
LITTLE_ENDIAN 内存数据 [4, 3, 2, 1]

 

三、Java 与 javascript 字节转换

如果通信的双方都是Java,则根本不用考虑字节序的问题了。 

Java 的 byte 范围是[-128, 127],

JavaScript 的 byte 范围是[0, 256]

 

四、int 与 byte Array 转换示例

转换时使用相同的字节序

    // 生成4个字节的网络字节序,网络传输使用大端字节序,相当于int2ByteArray
    byte[] getNetworkBytesOrder(int sourceNumber) {
        byte[] orderBytes = new byte[4];
        orderBytes[3] = (byte) (sourceNumber & 0xFF);
        orderBytes[2] = (byte) (sourceNumber >> 8 & 0xFF);
        orderBytes[1] = (byte) (sourceNumber >> 16 & 0xFF);
        orderBytes[0] = (byte) (sourceNumber >> 24 & 0xFF);
        return orderBytes;
    }

    // 还原4个字节的网络字节序, 相当于byteArray2Int
    int recoverNetworkBytesOrder(byte[] orderBytes) {
        int sourceNumber = 0;
        for (int i = 0; i < 4; i++) {
            sourceNumber <<= 8;
            sourceNumber |= orderBytes[i] & 0xff;
        }
        return sourceNumber;
    }

 

        System.out.println(Arrays.toString(intToByteArray(32)));
        System.out.println(Arrays.toString(intToByteArray(145)));
        System.out.println(Arrays.toString(intToByteArray(256)));

        System.out.println(Arrays.toString(intToByteArray2(32)));
        System.out.println(Arrays.toString(intToByteArray2(145)));
        System.out.println(Arrays.toString(intToByteArray2(256)));
       
        //还原
        System.out.println(byteArrayToInt2(intToByteArray2(145)));
        System.out.println(byteArrayToInt(intToByteArray2(145)));

 

输出

[0, 0, 0, 32]
[0, 0, 0, -111]
[0, 0, 1, 0]
[0, 0, 0, 32]
[0, 0, 0, -111]
[0, 0, 1, 0]
145
145

    public static byte[] intToByteArray(int i) {
        byte[] result = new byte[4];
        result[0] = (byte)((i >> 24) & 0xFF);
        result[1] = (byte)((i >> 16) & 0xFF);
        result[2] = (byte)((i >> 8) & 0xFF);
        result[3] = (byte)(i & 0xFF);
        return result;
    }

    public static byte[] intToByteArray2(int i) {
        return ByteBuffer
                .allocate(4)
//                默认大端字节序
//                .order(ByteOrder.LITTLE_ENDIAN)
                .putInt(i)
                .array();
    }


    public static int byteArrayToInt2(byte[] byteArray) {
        int value = 0;
        for (int i = 0; i < 4; i++) {
            int shift = (4 - 1 - i) * 8;
            value += (byteArray[i] & 0x000000FF) << shift;
        }
        return value;
    }

    public static int byteArrayToInt(byte [] byteArray){
        return ByteBuffer.wrap(byteArray)
//                默认大端字节序
//                .order(ByteOrder.LITTLE_ENDIAN)
                .getInt();
    }

 

以上是关于主机字节序 与 网络字节序的主要内容,如果未能解决你的问题,请参考以下文章

第五篇:主机字节序与网络字节序的转换

主机字节序 与 网络字节序

网络字节序与主机字节序的转换

网络字节序与主机字节序的转换

网络字节序与主机字节序的转换

主机序和网络序以及使用例子