V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
gino86
V2EX  ›  程序员

网络编程中文件传输是否需要处理大小端的问题,如何处理?

  •  
  •   gino86 · 2016-12-26 10:45:33 +08:00 · 4404 次点击
    这是一个创建于 2671 天前的主题,其中的信息可能已经有所发展或是发生改变。
    第 1 条附言  ·  2016-12-26 20:29:29 +08:00
    在 python 文档的 how to 部分找到下面的内容:

    It is perfectly possible to send binary data over a socket. The major problem is that not all machines use the same formats for binary data. For example, a Motorola chip will represent a 16 bit integer with the value 1 as the two hex bytes 00 01. Intel and DEC, however, are byte-reversed - that same 1 is 01 00. Socket libraries have calls for converting 16 and 32 bit integers - ntohl, htonl, ntohs, htons where “ n ” means network and “ h ” means host, “ s ” means short and “ l ” means long. Where network order is host order, these do nothing, but where the machine is byte-reversed, these swap the bytes around appropriately.
    18 条回复    2016-12-27 09:27:49 +08:00
    phrack
        1
    phrack  
       2016-12-26 10:59:57 +08:00
    啥?

    难道文件传输不是直接按字节流传的吗?

    难道大小端不是只在多字节整数还是什么的上面才考虑吗?
    zjbztianya
        2
    zjbztianya  
       2016-12-26 11:01:18 +08:00
    把主机序转换成网络字节序就可以了
    gino86
        3
    gino86  
    OP
       2016-12-26 11:05:33 +08:00
    @phrack 对于大小端模式的概念我本身并不是很清晰,文件以字节流的形式传输这个我知道,因为之前看 python 文档网络编程部分的时候见到一个注意事项,关键字好像有提到文件传输,大小端这个方面的,发帖前我也有重新翻文档,但就是找不到,所以有此一问
    q397064399
        4
    q397064399  
       2016-12-26 11:09:12 +08:00
    @gino86
    大小端是指程序变量 在内存中地址映射的问题吧,
    跟网络文件没有关系,所有的文件都是有序字节流,没有大小端这个概念
    weaming
        5
    weaming  
       2016-12-26 12:32:06 +08:00
    raysonx
        6
    raysonx  
       2016-12-26 13:50:36 +08:00 via Android
    大小端序问题关注的是一个多字节数在内存中的表示形式。
    比如 0x12345678 ,在大端序机器的内存中表示为 12 34 56 78 ,小端序表示为 78 56 34 12 。则如果凭空给你一个字节流不告诉你大小端序的话,你是不知道它代表多少的。
    因此,如果两台机器以不同的方式解读同一个字节流,则结果是不一样的。于是在网络协议中大家就约定好都用大端序表示多字节数。其实这无所谓,只要通信双方约定好用同一个字节序来解读
    raysonx
        7
    raysonx  
       2016-12-26 13:54:14 +08:00 via Android   ❤️ 1
    不会有歧义。
    至于传输文件,你负责的只是原封不动地把一台机器的数据搬到另一台,又不负责对内容进行解读,这些数据无关大小端序。但是如果你要处理网络协议头中的字段,那就看协议的规定了。虽说通常都是大端序的,但如果那个协议是个私有协议,谁知道呢。
    gino86
        8
    gino86  
    OP
       2016-12-26 14:07:48 +08:00
    @raysonx 是不是说,网络之间的文件传输也是有大小端之分,只不过协议已经帮我们处理好了?
    raysonx
        9
    raysonx  
       2016-12-26 15:19:35 +08:00
    @gino86 可能是我表述得不清楚,也可能是你还沒有理解。
    這個問題和網絡沒有關係,你可以把網絡看成一個管道,你在這一頭發送什麼,另一頭就能原封不動地收到什麼。
    大小端序只是一個多字節數在內存中的表示形式,跨機器時要注意解讀的順序。
    ryd994
        10
    ryd994  
       2016-12-26 16:05:10 +08:00 via Android
    @gino86 内存就是一个柜子,一个抽屉一字节。一个 short 两字节,一上一下,两个顺序都可以。但是 CPU 只认一种。
    而网络是个管道,你把抽屉里的东西倒进管道里,一次一抽屉,先倒先出,反正没什么上下关系。
    对面也是原样接收。只有在对面需要解读这个数的时候,才需要考虑字节序。
    scnace
        11
    scnace  
       2016-12-26 16:15:38 +08:00
    小端都是异类。(逃
    ryd994
        12
    ryd994  
       2016-12-26 16:16:37 +08:00 via Android
    你这个问题就是抽象思维没有到
    传输一个文件并不需要明白这个文件的含义。这就是一串 byte 。反正原样发送原样接受,这个文件传输就搞定了。至于这个文件是大端小端, who cares ?你发的是啥收到就是啥。

    另外,大多数网络协议约定俗成大端,但私有协议爱怎么玩怎么玩。不过协议用什么顺序和你文件内容又有什么关系呢?文件内容保证原样送达就行。
    gino86
        13
    gino86  
    OP
       2016-12-26 17:18:38 +08:00
    @ryd994 大概明白了,就是我们爱怎么就怎么,剩下的交给 cpu 去解析
    HelloiWorld
        14
    HelloiWorld  
       2016-12-26 23:23:02 +08:00 via iPhone
    据我所知苹果是小端序,最近用 Protobuf 向后台发二进制流之前要先转端序,其他网络是大端序
    kkzxak47
        15
    kkzxak47  
       2016-12-27 08:33:26 +08:00 via Android
    单个字节不存在大小端的问题
    P0P
        16
    P0P  
       2016-12-27 09:03:27 +08:00
    @scnace @HelloiWorld 这跟 cpu 有关,跟系统基本无关, x86 机器都是小端
    araraloren
        17
    araraloren  
       2016-12-27 09:15:48 +08:00
    基于 socket 的数据传输传输的是二进制流,顺序和字节都会原封不动的传输过去,这和你从一个文件中读取一段数据一样一样的
    需要注意大小端的是对整数解读问题,因为整数的数值涉及到了字节序(所以说只有两个以上的字节才有顺序问题, socket 传输的数据可以看作 char*,亦即不存在这种顺序问题)问题,比如大端数值为`0x1234`的两个字节原封不动搬到另一个小端机器解读的时候就是`0x3412`了,注意这时候内存中的字节内容、顺序是不变的
    wizardoz
        18
    wizardoz  
       2016-12-27 09:27:49 +08:00
    文件传输 不存在 大小端问题!!!!
    文件传输 不存在 大小端问题!!!!
    文件传输 不存在 大小端问题!!!!

    大小端问题是在内存数据中,不同的 CPU 架构可能会使用不同的顺序存储多字节整数的高低字节.
    只有整数存在大小端问题,浮点数和单字节字符,字符串均没有大小端问题.(宽字节有没有大小端问题我不知道)

    当然如果写一个程序,直接把运行的程序中一些数据保存到文件中,那么在保存的文件只能在同样架构的 CPU 主机上读取才是正确的.如果是标准的文件格式,那么存储的时候就的考虑序列化的问题.
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3202 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 10:49 · PVG 18:49 · LAX 03:49 · JFK 06:49
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.