71.大小端模式

71.消息处理-其他-大小端模式


71.1 知识点

什么是大小端模式

大端模式

  • 数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中。
  • 这种存储模式类似于将数据视为字符串顺序处理。
  • 地址由小向大增加,数据从高位往低位放置。
  • 符合人类的阅读习惯。

小端模式

  • 数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中。

举例说明

  • 十六进制数据 0x11223344,44 是最低字节,11 是最高字节。
  • 大端模式存储:
    11    22    33    44
    0     1     2     3
    
  • 小端模式存储:
    44    33    22    11
    0     1     2     3
    

为什么有大小端模式

  • 大小端模式是计算机硬件的两种存储数据的方式,也称为大小端字节序。
  • 计算机内部处理时,不知道什么是高位字节,什么是低位字节,只按顺序读取字节。
  • 计算机电路先处理低位字节,效率较高,因此采用小端模式。
  • 我们人类的读写习惯是大端字节序,但在计算机内部处理时,采用小端字节序。
  • 在网络传输和文件存储等场合,一般采用大端模式。

大小端模式对于我们的影响

  • 只有读取的时候,才必须区分大小端字节序,其它情况都不用考虑。
  • 在网络传输中,前后端语言、设备可能导致大小端不统一,需要进行大小端转换。
  • 通常,C# 和 Java/Erlang/AS3 通讯需要进行大小端转换,而 C# 与 C++ 通信不需要特殊处理。

大小端转换

BitConverter.IsLittleEndian 判断是大小端哪种模式

print("是否是小端模式:" + BitConverter.IsLittleEndian);

IPAddress.HostToNetworkOrder 转为大端模式

// 1. 本机字节序转网络字节序 HostToNetworkOrder 方法
//转换为网络字节序 相当于就是转为大端模式
int i = 99;
byte[] bytes = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(i));

IPAddress.NetworkToHostOrder 转为小端模式

// 2. 网络字节序转本机字节序 NetworkToHostOrder 方法
//网络字节序转换为本机字节序 相当于就是转为小端模式
int receI = BitConverter.ToInt32(bytes, 0);
receI = IPAddress.NetworkToHostOrder(receI);

Array.Reverse 倒序数组转换

//数组中的倒序API
//如果后端需要用到大端模式 那么我们进行判断
//如果当前是小端模式 就进行一次 大小端转换
if (BitConverter.IsLittleEndian)
    Array.Reverse(bytes);

总结

  • 大小端模式会根据主机硬件环境、语言而有所区别。
  • 在前后端语言不同且运行在不同主机上时,需要对大小端字节序定下统一的规则。
  • 一般让前端迎合后端,以减轻后端的负担,特别是在网络游戏中。
  • 注意在开发中发现消息不一致时,考虑大小端模式带来的影响。
  • 使用 Protobuf 可以简化大小端转换的问题。

71.2 知识点代码

using System;
using System.Collections;
using System.Collections.Generic;
using System.Net;
using UnityEngine;

public class Lesson71_消息处理_其它_大小端模式 : MonoBehaviour
{
    void Start()
    {
        #region 知识点一 什么是大小端模式

        //大端模式
        //是指数据的高字节保存在内存的低地址中
        //而数据的低字节保存在内存的高地址中
        //这样的存储模式有点儿类似于把数据当作字符串顺序处理
        //地址由小向大增加,数据从高位往低位放
        //符合人类的阅读习惯

        //小端模式
        //是指数据的高字节保存在内存的高地址中
        //而数据的低字节保存在内存的低地址中

        //举例说明
        //十六进制数据0x11223344 44是最低字节 11是最高字节

        //大端模式存储 适合人类理解
        // 11    22    33    44
        // 0     1     2     3
        //低地址——>高地址 

        //小端模式存储 适合计算机读取
        // 44    33    22    11
        // 0     1     2     3
        //低地址——>高地址

        #endregion

        #region 知识点二 为什么有大小端模式

        //大小端模式其实是计算机硬件的两种存储数据的方式
        //我们也可以称大小端模式为 大小端字节序

        //对于我们来说,大端字节序阅读起来更加方便,为什么还要有小端字节序呢?
        //原因是,计算机电路先处理低位字节,效率比较高
        //计算机处理字节序的时候,不知道什么是高位字节,什么是低位字节
        //它只知道按顺序读取字节,先读第一个字节,再读第二个字节
        //如果是大端字节序,先读到的就是高位字节,后读到的就是低位字节
        //小端字节序正好相反

        //因为计算机都是从低位开始的
        //所以,计算机的内部处理都是小端字节序

        //但是,我们人类的读写习惯还是大端字节序
        //所以,除了计算机的内部处理
        //其它场合几乎都是大端字节序,比如网络传输和文件存储

        //一般情况下,操作系统都是小端模式,而通讯协议都是大端模式
        //但是具体的模式,还是要根据硬件平台,开发语言来决定
        //主机不同,开发语言不同 可能采用的大小端模式也会不一致

        #endregion

        #region 知识点三 大小端模式对于我们的影响

        //我们记住一句话:
        //只有读取的时候,才必须区分大小端字节序,其它情况都不用考虑

        //因此对于我们来说,在网络传输当中我们传输的是字节数组
        //那么我们在收到字节数组进行解析时,就需要考虑大小端的问题
        //虽然TCP/IP协议规定了在网络上必须采用网络字节顺序(大端模式)
        //但是具体传输时采用哪种模式,都是根据前后端语言、设备决定的

        //在进行网络通讯时,前后端语言不同时,可能会造成大小端不统一
        //一般情况下
        //C# 和 Java/Erlang/AS3 通讯需要进行大小端转换 因为C#是小端模式 Java/Erlang/AS3是大端模式
        //C# 与 C++通信不需要特殊处理 他们都是小端模式

        #endregion

        #region 知识点四 大小端转换

        #region 1.判断是大小端哪种模式
        print("是否是小端模式:" + BitConverter.IsLittleEndian);
        #endregion

        #region 2.简单的转换API 只支持几种类型
        //转换为网络字节序 相当于就是转为大端模式
        //1. 本机字节序转网络字节序 HostToNetworkOrder方法
        int i = 99;
        byte[] bytes = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(i));
        //2. 网络字节序转本机字节序 NetworkToHostOrder方法
        int receI = BitConverter.ToInt32(bytes, 0);
        receI = IPAddress.NetworkToHostOrder(receI);
        #endregion

        #region 3.通用的转换方式
        //数组中的倒序API
        //如果后端需要用到大端模式 那么我们进行判断
        //如果当前是小端模式 就进行一次 大小端转换
        if (BitConverter.IsLittleEndian)
            Array.Reverse(bytes);
        #endregion

        #endregion

        #region 总结

        //大小端模式会根据主机硬件环境不同、语言不同而有所区别
        //当我们前后端是不同语言开发且运行在不同主机上时
        //前后端需要对大小端字节序定下统一的规则

        //一般让前端迎合后端,因为字节序的转换也是会带来些许性能损耗的
        //网络游戏中要尽量减轻后端的负担

        //一般情况下
        //C# 和 Java/Erlang/AS3 通讯需要进行大小端转换 前端C#从小变大
        //C# 与 C++通信不需要特殊处理

        //我们不用死记硬背和谁通讯要注意大小端模式
        //当开发时,发现后端收到的消息和前端发的不一样
        //在协议统一的情况下,往往就是因为大小端造成的
        //这时我们再转换模式即可

        //注意:
        //Protobuf已经帮助我们解决了大小端问题
        //即使前后端语言不统一
        //使用它也不用过多考虑字节序转换的问题

        #endregion
    }
}


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com

×

喜欢就点赞,疼爱就打赏