官方服务微信:dat818 购买与出租对接

大端与小端字节序详解:网络传输中的高低字节存储顺序解析

2万

主题

2

回帖

7万

积分

管理员

积分
73296
发表于 2025-4-1 21:31:57 | 显示全部楼层 |阅读模式
    首先明确大端、小端概念:

    大端:高字节存放低地址,低字节存放高地址;

    小端:低字节存放低地址,高字节存放高地址。

    再明确一个概念,网络字节序

    网络传输的数据为字节流。对于像占 4 个字节的 int 这样的多字节数值,在进行网络传输时,需明确先传递哪个字节。也就是说,接收端收到第一个字节后,要确定将其作为高位字节还是低位字节处理,这是一个有意义的问题。

    UDP/TCP/IP 协议规定:需将收到的第一个字节视为高位字节。这意味着发送方发送的第一个字节必须是高位字节。然而,发送方在发送时,只能从存储该变量的起始地址开始,逐个字节地进行发送。只有大端字节序能够满足这一要求。网络要求先发出去的必须是变量的高地址,而实际机器中是要从低地址开始一字节一字节地发,这两句话结合起来就意味着只有机器是大端字节序才刚好能满足要求。所以网络字节序是大端字节序,并且网络协议会使用大端字节序来传输数据。

    我们可以发现一个问题,若机器是大端,它就会按照大端的要求发出;若机器是小端,不做任何处理发出去的就是小端。是的,这就出现了以下现象:

    我们的机器一般是小端字节序。在进行网络数据传输时,最初建立连接并进行初始化操作时,常常需要先将 IP 和端口转换为大端模式(通过使用 htons 函数)。

    网络传输协议规定了传输使用大端字节序。那为什么只把 IP 地址、端口等转成大端格式呢?而数据部分却不进行大小端转换呢?

   


    我纠结这个问题还纠结了很久,答案是没有必要。

    首先明确 IP 地址和端口需要大端化的原因。网络传输协议规定要进行大端化,所以各级交换机和路由器在提取报文中的 MAC、IP 时也应该采用大端化方式。这样做的好处是统一规范,便于进行比对以查找路由表。

    为什么数据部分不大端化呢?数据大小端的差异和机器的存储方式相关,与传输方式没有关系。也就是说,网络包是以大端的方式进行传输的,当传输到本地对包进行解析时,不管是按大端传来的还是按小端传来的,接收方把变量赋值给本地变量时,都只能将先拿到的字节存放在低地址。如果发送端和接收端都是大端,那么解析存储的变量就没有问题;如果发送端和接收端都是小端,那么存储的变量在解析时也没有问题。然而,如果一端是大端机器,另一端是小端机器呢?大端机器会按照先发出的是高字节来发出数据,小端机器也会在分配好的内存位置按照顺序一个一个地存储数据,但是当从地址处取值读取时就会出现问题。所以网络传输只是规定要以大端字节序进行传输,然而它自身并不负责转换的事宜,内核也不会负责。至于具体是否要进行转换、转换哪些以及如何转换等问题,都需要各位依据具体的情况亲自去处理,而不是将其交给网络传输让它在传输过程中为你转换好。

    所以与之相对应的现象是,在接收到数据之后,若想要获取发送方的 IP 地址和端口,就需要将大端字节序进行本地化。数据部分,你那边的存储方式是什么,你发给我后我就按照你发的方式存储。只要不是一个大端一个小端,我接收完后就能正常解析。所以没必要在发送时转换一次,接收时又转换回来。交换机和路由器不需要关心你传输的数据是什么,你只需将它们所需的 IP 和端口按照大端转换好,这样它们才能正确找到路由。对于数据而言,无论你以何种方式发送,亦或是按照何种格式发送,网络都会将其认定为大端。然而,实际上是否为大端,你自己心中有数即可。

    附加一点笔记有个知识点有点忘记了:

    和是什么关系?

    先放点代码在这

<p style='margin-bottom:15px;color:#555555;font-size:15px;line-height:200%;text-indent:2em;'>    <pre><code> int   sockfd;  
定义了一个名为 m_addr 的 sockaddr_in 结构体。
创建一个用于网络通信的套接字,将其赋值给 sockfd 。该套接字的地址族为 AF_INET ,类型为 SOCK_STREAM ,协议参数为 0 。
   


m_addr 的 sin_family 被设置为 AF_INET 。
m_addr 的 sin_port 被设置为 htons(MYPORT) 。
inet_addr("192.168.0.106") 被赋值给 m_addr 的 sin_addr 的 s_addr 。
   
将 my_addr.sin_zero 清零,清零的长度为 8 。
   
将 sockfd 与 (struct sockaddr *)&m_addr 进行绑定,绑定的长度为 sizeof(struct sockaddr)。</code></pre></p>
    它只是一个用于通信的符号,所存储的是具体通信需要的信息。将其绑定在上,如此一来,这个管就能负责与里面地址的通信。

更多帖子推荐

您需要登录后才可以回帖 登录 | 立即注册

Archiver|手机版|小黑屋|关于我们

Copyright © 2001-2025, Tencent Cloud.    Powered by Discuz! X3.5    京ICP备20013102号-30

违法和不良信息举报电话:86-13718795856 举报邮箱:hwtx2020@163.com

GMT+8, 2025-4-12 19:12 , Processed in 0.084665 second(s), 18 queries .