大小端及网络字节序分析

大小端及网络字节序分析

一、什么是大端模式、小端模式

  1. 大端字节序(Big Endian):最高有效位存于最低内存地址处,最低有效位存于最高内存处;
  2. 小端字节序(Little Endian):最高有效位存于最高内存地址,最低有效位存于最低内存处。

二、Wireshark抓包分析大小端

小端:如下图

小端示例
小端示例

即在抓包的时候显示的数据是颠倒顺序显示的,即4字节的数值显示的值是:0x01 0x00 0x00 0x00,但是实际的值是0x00 0x00 0x00 0x01即值为1

大端:如下图

大端示例
大端示例

即在抓包的时候显示的数据是正常顺序显示的,即4字节的数值显示的值是:0x00 0x00 0x10 0x00,实际值就是4096

三、网络字节序

  网络上传输的数据都是字节流,对于一个多字节数值,在进行网络传输的时候,先传递哪个字节?也就是说,当接收端收到第一个字节的时候,它将这个字节作为高位字节还是低位字节处理,是一个比较有意义的问题;

  UDP/TCP/IP协议规定:把接收到的第一个字节当作高位字节看待,这就要求发送端发送的第一个字节是高位字节;而在发送端发送数据时,发送的第一个字节是该数值在内存中的起始地址处对应的那个字节,也就是说,该数值在内存中的起始地址处对应的那个字节就是要发送的第一个高位字节(即:高位字节存放在低地址处);由此可见,多字节数值在发送之前,在内存中因该是以大端法存放的;

  所以说,网络字节序是大端字节序;

  在实际中,当在两个存储方式不同的主机上传输时,需要借助字节序转换函数。

四、C#字节数据与数值的转换

/// <summary>
/// byte字节数组转int(大端)
/// </summary>
/// <param name="src">数据源</param>
/// <param name="offset">数据所在的偏移量</param>am>
/// <param name="len">要转换的长度</par
/// <returns></returns>
public static int BytesToInt(byte[] src, int offset, int len)
{
    switch (len)
    {
        case 2:
            return (src[offset++] & 0xFF) << 8 |
                    src[offset++];
        case 3:
            return (src[offset++] & 0xFF) << 16 |
                   (src[offset++] & 0xFF) << 8 |
                    src[offset++];
        case 4:
            return (src[offset++] & 0xFF) << 24 |
                   (src[offset++] & 0xFF) << 16 |
                   (src[offset++] & 0xFF) << 8 |
                    src[offset++];
        default:
            return 0;
    }
}

/// <summary>
/// int转byte字节数组(大端)
/// </summary>
/// <param name="value">数值</param>
/// <param name="len">转换的长度</param>
/// <returns></returns>
public static byte[] IntToBytes(int value, int len)
{
    byte[] src = new byte[len];
    switch (len)
    {
        case 1:
            src[0] = (byte)(value & 0xFF);
            break;
        case 2:
            src[0] = (byte)((value >> 8) & 0xFF);
            src[1] = (byte)(value & 0xFF);
            break;
        case 3:
            src[0] = (byte)((value >> 16) & 0xFF);
            src[1] = (byte)((value >> 8) & 0xFF);
            src[2] = (byte)(value & 0xFF);
            break;
        case 4:
            src[0] = (byte)((value >> 24) & 0xFF);
            src[1] = (byte)((value >> 16) & 0xFF);
            src[2] = (byte)((value >> 8) & 0xFF);
            src[3] = (byte)(value & 0xFF);
            break;
    }

    return src;
}

/// <summary>
/// int转byte字节数组(小端)
/// </summary>
/// <param name="value">数值</param>
/// <param name="len">要转换成字节数组的长度</param>
/// <returns></returns>
public static byte[] IntToBytesEx(int value, int len)
{
    byte[] src = new byte[len];
    switch (len)
    {
        case 1:
            src[0] = (byte)(value & 0xFF);//低位
            break;
        case 2:
            src[1] = (byte)((value >> 8) & 0xFF);//高8位
            src[0] = (byte)(value & 0xFF);//低位
            break;
        case 3:
            src[2] = (byte)((value >> 16) & 0xFF);
            src[1] = (byte)((value >> 8) & 0xFF);//高8位
            src[0] = (byte)(value & 0xFF);//低位
            break;
        case 4:
            src[3] = (byte)((value >> 24) & 0xFF);
            src[2] = (byte)((value >> 16) & 0xFF);
            src[1] = (byte)((value >> 8) & 0xFF);//高8位
            src[0] = (byte)(value & 0xFF);//低位
            break;
    }
    return src;
}

/// <summary>
/// byte字节数组转int(小端)
/// </summary>
/// <param name="src"></param>
/// <param name="offset"></param>
/// <param name="len"></param>
/// <returns></returns>
public static int BytesToIntEx(byte[] src, int offset, int len)
{
    switch (len)
    {
        case 2:
            return ((src[offset++] & 0xFF) | //低位 
                    ((src[offset++] & 0xFF) << 8));
        case 3:
            return ((src[offset++] & 0xFF) | //低位 
                    ((src[offset++] & 0xFF) << 8) |
                    ((src[offset++] & 0xFF) << 16));
        case 4:
            return ((src[offset] & 0xFF) |//低位 
                    ((src[offset++] & 0xFF) << 8) |
                    ((src[offset++] & 0xFF) << 16) |
                    ((src[offset++] & 0xFF) << 24));
        default:
            return 0;
    }
}


 

 

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 大端(Big-Endian)模式:数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中。小端(Little-Endian)模式:数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中。 ### 回答2: 串口通信的大小端字节序取决于传输的数据类型。在串口通信中,数据通常以字节的形式进行传输。对于字节的存储方式,有两种常见的字节序:大端字节序(Big-Endian)和小端字节序(Little-Endian)。 大端字节序是指将数据的高位字节存储在内存的低地址中,而将数据的低位字节存储在内存的高地址中。这种存储方式常用于网络传输和大部分的大型计算机中。 小端字节序则是将数据的低位字节存储在内存的低地址中,而将数据的高位字节存储在内存的高地址中。这种存储方式常用于一些小型计算机和个人电脑中。 在串口通信中,字节的传输是按照其在内存中的存储顺序进行的。如果通信的两端采用相同的字节序,则数据能够正确地传输。然而,如果通信的两端采用不同的字节序,则数据在接收端可能会发生错误的解析。 为了确保正确的数据传输,通常需要在通信的两端进行字节序的转换。这可以通过将字节按照反转的方式进行重新排列来实现,从而使得传输的字节顺序与接收端相符。 总之,串口通信的大小端字节序是通过对字节的存储方式进行约定来确定的。如果通信双方采用相同的字节序,数据能够正确地传输。否则,需要进行字节序的转换以确保数据的正确解析。 ### 回答3: 串口通信的大小端字节序是指数据在传输过程中的存储顺序。在串口通信中,一个字节通常由8位二进制数据组成,而字节序指的是这8位二进制数据的存储顺序。 小端字节序(Little-endian)是指低位字节存储在内存的低地址处,而高位字节存储在内存的高地址处。在小端字节序中,数据的字节排列顺序是从低位到高位的顺序。例如,十六进制数0x12345678的存储顺序为0x78 0x56 0x34 0x12。 大端字节序(Big-endian)则是指高位字节存储在内存的低地址处,而低位字节存储在内存的高地址处。在大端字节序中,数据的字节排列顺序是从高位到低位的顺序。例如,十六进制数0x12345678的存储顺序为0x12 0x34 0x56 0x78。 在串口通信中,数据的传输是以字节为单位的。当数据从发送端传输到接收端时,发送端和接收端需要使用相同的大小端字节序,以保证数据的正确传输和解析。 需要注意的是,串口通信中的大小端字节序是由通信设备或协议决定的,而不是由计算机的架构决定的。所以,在进行串口通信时,需要了解所使用的通信设备或协议的字节序要求,并进行相应的处理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值