为了账号安全,请及时绑定邮箱和手机立即绑定

通过C中的套接字传递结构

通过C中的套接字传递结构

C
眼眸繁星 2019-07-26 15:47:32
通过C中的套接字传递结构我试图将整个结构从客户端传递到服务器,反之亦然。让我们假设我的结构如下struct temp {   int a;   char b;}我使用sendto并发送结构变量的地址,并使用recvfrom函数在另一侧接收它。但我无法获得接收端发送的原始数据。在sendto函数中,我将接收到的数据保存到struct temp类型的变量中。n = sendto(sock, &pkt, sizeof(struct temp), 0, &server, length);n = recvfrom(sock, &pkt, sizeof(struct temp), 0, (struct sockaddr *)&from,&fromlen);其中pkt是struct temp类型的变量。虽然我收到8字节的数据,但如果我尝试打印它只是显示垃圾值。任何帮助修复它?注意: 不得使用第三方库。编辑1:我对这个序列化概念真的很陌生。但是如果不进行序列化,我不能通过套接字发送结构?EDIT2:当我尝试使用sendto和recvfrom函数发送字符串或整数变量时,我在接收端正确接收数据。为什么不在结构的情况下?如果我不必使用序列化功能,那么我应该单独发送每个结构的成员吗?这实际上不是一个合适的解决方案,因为如果有'n'个成员,那么只有添加'n'个代码行才能发送或接收数据。
查看完整描述

3 回答

?
慕娘9325324

TA贡献1783条经验 获得超4个赞

这是一个非常糟糕的主意。二进制数据应始终以下列方式发送:

不要以二进制方式编写整个结构,而不是文件,而不是套接字。

始终分别编写每个字段,并以相同的方式读取它们。

你需要有像这样的功能

unsigned char * serialize_int(unsigned char *buffer, int value){
  /* Write big-endian int value into buffer; assumes 32-bit int and 8-bit char. */
  buffer[0] = value >> 24;
  buffer[1] = value >> 16;
  buffer[2] = value >> 8;
  buffer[3] = value;
  return buffer + 4;}unsigned char * serialize_char(unsigned char *buffer, char value){
  buffer[0] = value;
  return buffer + 1;}unsigned char * serialize_temp(unsigned char *buffer, struct temp *value){
  buffer = serialize_int(buffer, value->a);
  buffer = serialize_char(buffer, value->b);
  return buffer;}unsigned char * deserialize_int(unsigned char *buffer, int *value);

或者等效,当然有几种方法可以设置缓冲区管理等等。然后,您需要执行序列化/反序列化整个结构的更高级函数。

这假设序列化是从缓冲区完成的,这意味着序列化不需要知道最终目标是文件还是套接字。它还意味着您需要支付一些内存开销,但出于性能原因,它通常是一个很好的设计(您不希望对套接字执行每个值的write())。

完成上述操作后,您可以通过以下方式序列化和传输结构实例:

int send_temp(int socket, const struct sockaddr *dest, socklen_t dlen,
              const struct temp *temp){
  unsigned char buffer[32], *ptr;

  ptr = serialize_temp(buffer, temp);
  return sendto(socket, buffer, ptr - buffer, 0, dest, dlen) == ptr - buffer;}

关于上述几点需要注意:

  • 要发送的结构首先按字段顺序序列化为buffer

  • 序列化例程返回一个指向缓冲区中下一个空闲字节的指针,我们用它来计算它序列化的字节数

  • 显然,我的示例序列化例程不能防止缓冲区溢出。

  • 如果sendto()调用成功,则返回值为1 ,否则为0。


查看完整回答
反对 回复 2019-07-26
?
吃鸡游戏

TA贡献1829条经验 获得超7个赞

使用'pragma'包选项确实解决了我的问题,但我不确定它是否有任何依赖?

#pragma pack(1)   // this helps to pack the struct to 5-bytesstruct packet {int i;char j;};#pragma pack(0)   // turn packing off

然后下面的代码行没有任何问题

n = sendto(sock,&pkt,sizeof(struct packet),0,&server,length);n = recvfrom(sock, &pkt, sizeof(struct packet), 0, (struct sockaddr *)&from, &fromlen);


查看完整回答
反对 回复 2019-07-26
?
慕的地10843

TA贡献1785条经验 获得超8个赞

有没有必要写自己的序列化程序shortlong整数类型-使用htons()htonl()POSIX功能。


查看完整回答
反对 回复 2019-07-26
  • 3 回答
  • 0 关注
  • 451 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信