zoukankan      html  css  js  c++  java
  • 网络数据(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时会导致数据截断。

  • 相关阅读:
    Java之ServiceLoader
    docker学习(3)--Dockfile详解
    docker学习(2)--基础命令
    docker学习(1)--基础概念
    dubbo学习(1)--简单的入门搭建实例
    Flume搭建及学习(基础篇)
    VM下--Linux根分区磁盘扩容
    Windows10下简单搭建zookeeper
    Windows10下搭建TensorFlow环境
    cmath库函数
  • 原文地址:https://www.cnblogs.com/lidabo/p/3778991.html
Copyright © 2011-2022 走看看