【问题标题】:pointers inside a struct with send带有发送的结构内的指针
【发布时间】:2012-12-22 00:07:46
【问题描述】:

我有以下结构,我正在尝试通过网络发送到另一个应用程序

 struct protocol
  {

     char protocol;
     char field1;
     char field2;
     char field3;
     char field4;
     char field5;
     char field6;
     char field7;
     char field8;
     char msg_id;
     char msg_length;
     char *msg;

  };

我遇到的问题是我不确定如何通过网络发送此结构,因为其中有一个指向字符串的指针,并且 memcpy 到缓冲区的结构不起作用,如下所示唯一的办法吗?

memcpy (buffer, protocol->protocol, char)
memcpy (buffer, protocol->field1, char)
...
memcpy (buffer, protocol->msg, protocol->length)

然后发送缓冲区

【问题讨论】:

  • 你是如何序列化这个结构的?
  • 我不是,我该怎么做?
  • 这取决于您的发送者和接收者。基本上,您发送的任何数据都需要成为字节流,正如您所指出的,这意味着需要解析嵌入式指针。问题是,你如何把它变成一个流取决于对方的期望,因为它会重新组装。
  • 好的,我明白你在说什么,所以基本上像我提到的 memcpy 将数据复制到另一个变量就是序列化结构,对吗?
  • 是的。序列化基本上就是这样,但是有很多序列化的方法,这就是协议的用武之地。

标签: c pointers struct


【解决方案1】:

您需要将结构序列化为某种缓冲区。您的副本顺序仅在概念上是正确的;有无数的细节需要解决:

char buffer[sizeof(struct protocol) + protocol->msg_length]; // Over-allocation

buffer[0] = protocol->protocol;
buffer[1] = protocol->field1;
...
buffer[8] = protocol->field8;
buffer[9] = protocol->msg_id;
buffer[10] = protocol->msg_len;
memcpy(&buffer[11], protocol->msg, protocol->msg_len);

现在您可以写入要发送的正确长度的缓冲区 (11 + protocol->msg_len)。

这个特别简单;无需担心字节顺序问题。通常,对于像shortintlong long 这样的多字节值,您必须担心传输的字节顺序。

【讨论】:

    【解决方案2】:

    是的,如果您要发送到(可能)在您自己的流程之外的东西,那么这种编组或序列化是唯一可行的方法。

    【讨论】:

    • 谢谢,所以在这种情况下,如果有很多字段,那么会有很多 memcpy 不是那么实用,在这种应用程序中什么是实用的,我不需要使用 struct在这种情况下?
    • 不知道你还能如何解决它。显然,除了 memcpy 之外,还有其他方法,但不知何故,您需要获取所有小数据并制作一个大数据。正如下面 Jonathan Leffler 所示,您只能 memcpy 大缓冲区。或者您可以 memcpy 整个结构,除了最后一位 [依赖于结构中没有间隙 - 例如,您有奇数个 char 后跟一个 int,您会得到一个间隙,这可能与接收方正在接受!] 如果是字符串,而不是 char,则可以使用 sprintf 将结果打印到缓冲区中。
    【解决方案3】:

    如果您可以限制您发送的数据的某些方面,例如“msg_len 永远不会超过 X 字节”,您可以这样做:

    #define MAX_MSG_LEN 1000
    struct protocol
    {
     char protocol;
     char field1;
     char field2;
     char field3;
     char field4;
     char field5;
     char field6;
     char field7;
     char field8;
     char msg_id;
     char msg_length;
     char msg[MAX_MESSAGE_LEN];
    };
    

    您需要计算在 msg 之前有多少开销,然后使用 msg_length 确定您需要发送的缓冲区的总大小。

    或者,另一种方法是:

    struct protocol
    {
     char protocol;
     char field1;
     char field2;
     char field3;
     char field4;
     char field5;
     char field6;
     char field7;
     char field8;
     char msg_id;
     char msg_length;
     char msg[1];
    };
    

    然后在需要形成消息时使用struct procotol *msg_ptr = malloc(sizeof(struct protocol) + msg_len-1);

    这两种方法都有一个缺点,如果结构中有“间隙”,则需要在另一端处理它(如果使用不同的编译器编译,间隙可能有不同的规则,对于不同的处理器,或者只是使用不同的编译器开关)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-18
      • 1970-01-01
      • 2015-07-13
      • 2015-07-10
      相关资源
      最近更新 更多