• 网络数据(socket)传输总结


    环境限定:TCP/IP下的socket网络传输;C/C++开发语言,32/64位机。

    目前有两种方式对数据进行传输:1)字符流形式,即将数据用字符串表示;2)结构型方式,即将数据按类型直接传输。

    1)的方式保证所有的数据都是清晰的字符串明文,没有平台不一致问题,但传输的数据不定长,复合数据类型(如struct)的解析不方便。
    2)的方式保证数据长度固定/可控,方便对接受到数据的解析;但前提是要考虑平台不一致问题,如字节序、对齐位宽、数据类型等;


    两种数据传输方式应用时的注意点:
    1)字符流形式 -- 需要协商好数据的解析方式,考虑到数据不定长可能导致的问题。
    2)结构形式 -- 主要注意平台不一致导致的问题。


    字符流传输方式相对简单、安全,以结构方式传输则不同。结构形式传输数据时,要检查下面各点:
    1)首先要清楚是否有机器位宽不一致的情况,如32位机和64位机。如果位宽不一致,则避免传输表示方式不一致的数据类型,如long、float型在32位了64位下表示方式不一致,会导致数据解析错误。
    2)确认通信双方的对齐位宽一致,或自己保证传输的数据结构在对齐调整后不会产生大小不一致。如果收发双方的对齐方式分别是按4和8字节对齐,则需要在程序中明确制定对齐位宽;或者调整数据的结构,确保在对齐调整后,收/发的数据中每一项的偏移量一致。
    3)尽量对发出去的数据都转换成网络字节序,接收后转换回本地字节序,特别是机器字节序不一致时,现有的字节序转换函数不能满足所有需求。
    4)某些数据类型的表示方式有不同,如浮点数(一般用IEEE 794标准),不能认为正确的传了一个字节序正确的8字节double型就对了,不同平台对double型的表示方式不同,比如发送1.003,接受没问题,结果却得到了其它的数值。

    传结构型数据时对字节序和浮点数的处理,以下的两点网上的资料不多,详细记录一下:
    1)目前没有对8字节或以上数据类型的转换函数,需要自己实现,网上有很多,下面例举一个:
    uint64_t htonll(uint64_t n) {
    return (((uint64_t)htonl(n)) << 32) | htonl(n >> 32);
    }
    uint64_t ntohll(uint64_t n) {
    return (((uint64_t)ntohl(n)) << 32) | ntohl(n >> 32);
    }
    如果有更长的数据(12字节...),以此类推。

    2)对浮点数之类的数据,如果要完全准确,那么用字符串发送。如果直接传数据,仍要处理字节序,同时确保收发双方对浮点数的表示方式一致。下面是两个double型的字节序转换函数:
    double ntoh_double(double net_double) {
    uint64_t host_int64;
    host_int64 = ntohll(*((uint64_t *) &net_double));
    return *((double *) &host_int64);
    }

    double hton_double(double host_double) {
    uint64_t net_int64;
    net_int64 = htonll(*((uint64_t *) &host_double));
    return *((double *) &net_int64);
    }
    上述函数之所以没有对host_double/net_double直接转成uint64_t时会导致数据截断。

  • 相关阅读:
    水晶报表关于System.Web.Extensions报错的问题
    个人下一步学习计划
    一个老程序员对数据库的一点纠结
    Visual SourceSafe权限配置记录
    SQL SERVER 2008代码折叠小技巧
    用命令行自动备份数据库到其他服务器
    CrystalReports 2008序列号留档
    ····
    C语言中的static
    页面自动刷新的几种方法
  • 原文地址:https://www.cnblogs.com/lidabo/p/3778991.html
Copyright © 2020-2023  润新知