send函数可以直接发送结构体吗?

       网络通信编程中,常常用结构体对待发送的数据进行封装。比如,

struct msg { charcmd;  char len;  int extraData[0]; };

cmd表示命令,远端会根据cmd进行不同的处理;extraData是要发送的数组;len则表示extraData的占用的内存字节数。

       在这种设计下,当需要发送数据时,把根据数据长度增加整个struct msg的内存(一般是定义struct msg指针,然后用realloc函数重新分配),然后把待发送数据填入extraData指向的内存单元(就是新增加的内存单元)。再把数据长度填入len,命令填入cmd。

       struct msg  *clientMsg = (struct msg *)malloc(sizeof(structmsg));

       clientMsg->cmd =CMD_COMPUTE;

       clientMsg->len = 12;

       clientMsg = (struct msg *)realloc(clientMsg, sizeof(struct msg) + 12 );

       *(clientMsg->extraData) =11;

       *(clientMsg->extraData + 1) = 22;

       *(clientMsg->extraData + 3) = 33;

       那么,send函数的第二个参数能否填该结构体的地址呢?

send函数原型为:

ssize_t send(int sockfd, const void*buf, size_t len, int flags)

其意义是发送buf指向的内存的连续的len个字节单元。结构体的地址实质是一块连续内存单元的首地址,那么将其填在此处是符合逻辑的。

       然而,考虑到结构体的内存分布(参考本人另一篇博客《struct内存对齐》),一个结构体的内存中很有可能存在无效的字节。64位cpu中,msg结构体在内存中的分布为     

          地址:  0x8   0x9   0xa  0xb   0xc   0xd   0xe    0xf

          数据:|-----------data[1]----------|  |-----------data[2]----------|

占用单元数:        4                     4

          地址: 0x0    0x1    0x2   0x3   0x4   0x5   0x6   0x7 (共8个字节)

          数据:|cmd| |len|   |无效字节|  |--------data[0]----------|

占用单元数:  1     1        2            4

地址0x02-0x03为无效字节。如果将&data和sizeof(struct data)填入send函数,发送的将是从0x0到0xb的内存单元,包含了无效字节

       基于发送端对发送数据的操作,远端接收数据时,必须先拿到len值,然后根据该值增加extraData指向的内存单元个数,才能接收数据。

       struct msg  *clientMsg = (struct msg *)malloc(sizeof(structmsg));

       recv(sockfd, clientMsg,sizeof(struct msg));//此处取得cmd=CMD_COMPUTE和len =12

       clientMsg = (struct msg *)realloc(clientMsg, sizeof(struct msg) + clientMsg->len );//根据len值增加内存

       recv(sockfd, clientMsg->extraData,clientMsg->len);//接收extraData,此时会把发送端内存地址为0x02到0x0d的12个字节接收过来,然而,0x02到0x03为无效字节,且有效字节0x0e-0x0f没有被接收。

       综上所述,在此种情况下,发送结构体时不可直接填入其地址。

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值