关于socket通信中大小端转换问题

本人一直有个疑惑,大小端通信怎么存储(以前一直知道这个概念,但怎么都跟实际匹配不上,网络上也并没有说怎么处理大小端通信问题)

socket通信中 addr 需要转换成网络字节序,也就是大端

助记: htonl h-> host 缩写 n -> net 缩写 l 是类型缩写(l -> long  ll-> longlong s short 都是无符号的)

首先理解下,大小端  数据在内存的存储顺序不同,注意数据还是那个数据只是存储的方式不同

大端,数据的低位在内存的高位

小端,数据的低位在内存的低位

内存地址是按字节排序的 0x01 0x02 每个地址偏移是一个字节的内容。

数据 0x12345678  数据的从低到高 0x78 0x56 0x34 0x12.

大端 内存内数据 0x01-0x12 0x02-0x34 0x03-0x56 0x04-0x78

小端 内存内数据 0x01-0x78 0x02-0x56 0x03-0x34 0x04-0x12

socket传输的是字节流,byte[] 数组,我们分两种情况讨论 unsigned int var=0x12345678; 在网络中的传输状态。

1.两端 大小端 一致,则直接使用memcpy就可以,memcpy是内存数据的 大端会变成 0x12345678 数据传输到对端,把数据copy到内存中也是 0x12345678, 小端是 0x78563412, copy 到本地 也是这个值,毫无影响。

2.两端 大小端 不一致,变成byte数据的时候,memcpy是内存数据的 大端会变成 0x12345678 数据传输到对端,把数据copy到内存中也是 0x12345678,  这时cpu按内存地址认为值的话, 并不等于 数据0x12345678. 所以解析错误。小端同理。

解决办法,所以在socket传输多字节数据的情况下,需要把内存数据转为数据顺序(自定义的,可以从高到低,也可以从低到高,但是发送端和解析端必须一致)

比如说

void writeInt32(int v) {
    char buf[4] = {};
    buf[0] = (v >> 24) & 0xFF;
    buf[1] = (v >> 16) & 0xFF;
    buf[2] = (v >> 8) & 0xFF;
    buf[3] = (v >> 0) & 0xFF;
}
int readInt32(char[] buf) {
    int ch1 = buf[0];
    int ch2 = buf[1];
    int ch3 = buf[2];
    int ch4 = buf[3];
    return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));
}

上述这样操作,即可解决对应的字节流传输大小端问题。

题话外:

java 的数据类型都是大端,float 都是iee那个标准,也可以这种传输。

当然有更好的解决办法,用protobuf,protobuf数据里面就做了这种事情。

另外本地数据如果用memcpy存储到本地,不做这种处理的话,也会出现当前问题。

 

posted @ 2022-01-19 11:36  BackSword  阅读(1562)  评论(0编辑  收藏  举报