찾다

 >  Q&A  >  본문

c++ - 网络编程和字节对齐的问题?

struct TestClass
{    
    int a;
    double b;
};

这个结构体占用的内存的大小是16字节(windows下),它在内存里面按照double的字节大小对齐。

TestClass demo = {1, 1.1};

定义一个对象后,通过网络把这个demo对象发出去。

write(sockfd, &demo, sizeof(demo));

这样是发出去16个字节对吧?这样发出去的数据就包含了编译器字节对齐插进去的4个字节了吧?我的理解对吗?

如果把这个demo对象序列化为二进制的话是不是就是把demo里的int和double的值复制到一个缓冲区里,这样这个缓冲区的里面的值的长度就是12字节了(int + double)。这样的话,通过网络发送这个缓冲区里的数据的话就不包含字节对齐的值了吧,这就是序列化的意义吗?

求大神告诉我理解的对不对?不对的话我的哪些地方没有理解对呢?

天蓬老师天蓬老师2807일 전745

모든 응답(6)나는 대답할 것이다

  • 伊谢尔伦

    伊谢尔伦2017-04-17 13:16:46

    内存布局不可移植. 而且还有空隙.
    序列化就是为了移植. 各种语言遵守序列化的方式, 就可以反序列化出来对象, 可以把一个对象序列化. 这样就可以跨语言交互.

    회신하다
    0
  • ringa_lee

    ringa_lee2017-04-17 13:16:46

    序列化的意义在于,定义一种程序中的数据到字节串的对应关系(及其逆关系),以便用来存储、传输。这种关系是标准,与实现无关、与平台无关(不管你用什么 CPU,什么操作系统,什么编译器,什么编程语言,序列化的数据的解释方法都是预先定义好的)。

    当然也有局限于特定编程语言的序列化方案(比如 Python 的 pickle)。但那只是只有那种语言的实现而已,理论上你可以编写其它语言的程序来解释这些数据。

    회신하다
    0
  • 黄舟

    黄舟2017-04-17 13:16:46

    1.write(sockfd, &demo, sizeof(demo));
    这样发出去确实是16字节。
    但是你要明白write函数本身是跟字节对齐没关的。write函数本身只知道从哪个地址开始,发送多少字节的内容,write函数本身可不知道你的demo是什么结构。之所以会发送16个字节,是因为sizeof(demo)算出来是16字节。

    2.序列化是一些编程语言的库提供的,可以将数据映射为bytes用来存储或传输。反序列化就是从bytes重新进行加载还原。这两个过程是库本身提供的,库的开发者会确保这个过程在所有平台上都是可移植的。

    회신하다
    0
  • 怪我咯

    怪我咯2017-04-17 13:16:46

    说点题外话,网络编程最好显式pack,如64位机器按64位设计结构
    struct TestClass
    {

    int32 a;
    int32 _reversed;
    double b;

    };
    否则不同编译选项编译出来结果是不一样的,不一定都是16字节。

    회신하다
    0
  • 伊谢尔伦

    伊谢尔伦2017-04-17 13:16:46

    既然楼主这么虚心请教,就直说一下楼主理解的不对的地方吧:

    把这个demo对象序列化为二进制的话

    demo 这个 struct 原本就已经是二进制的了,write(sockfd, &demo, sizeof(demo)) 发送的就是二进制数据。

    是不是就是把demo里的int和double的值复制到一个缓冲区里

    复制?缓冲区?楼主是从哪里看来的这些概念,完全不是这样的……

    值的长度就是12字节了(int + double)

    为节省内存不浪费一个字节,可以用宏 #pragma pack(1) 来搞定。

    회신하다
    0
  • 伊谢尔伦

    伊谢尔伦2017-04-17 13:16:46

    http://www.cppblog.com/vczh/archive/2009/03/10/76098.html

    看我博客,详细解答

    회신하다
    0
  • 취소회신하다