如何使用.x文件生成的XDR结构(内存分配)

时间:2017-09-06 11:03:56

标签: c xdr

我想请一些关于这个案例的帮助。

我需要发送一条XDR消息,它由 2个文件组成( switch case == OK )。

假设我的代码中有一个名为message的{​​{1}}对象:

response

如果我只需要在邮件中发送一个文件,我会这样做:

message response;

缓冲区为:

response.message_u.fdata.last_mod_time         = last_modification;
response.message_u.fdata.contents.contents_len = file_size;
response.message_u.fdata.contents.contents_val = buffer;

现在,我了解buffer = malloc(file_size * sizeof(char)); 它是一个可变大小的数组(2是最大长度),我希望它们的索引为struct file fdata<2>;something[0]

另外我知道我需要分配内存,但在这种情况下我不知道如何使用多个文件。

我是否需要为我需要发送的所有内容执行一个malloc?像这样:

something[1]

response.message_u.fdata.fdata_val = malloc ( (file_size1 * sizeof(char)) + (file_size2 * sizeof(char)) + (2 * sizeof(uint32_t))); :每个要发送的文件的 last_mod_time

另一个问题是如何引用每个文件结构:

(2 * sizeof(uint32_t))

.x文件:

response.message_u.fdata[0]                        //?
response.message_u.fdata.last_mod_time[0]          //?
response.message_u.fdata[0].last_mod_time          //?
response.message_u.fdata.contents.contents_len[0]  //?
response.message_u.fdata.contents.contents_val[0]  //?

types.c(使用rpcgen生成):

enum tagtype {
    GET  = 0,
    OK   = 1,
    QUIT = 2,
    ERR  = 3
};

struct file {
    opaque contents<>;
    unsigned int last_mod_time;
};

typedef string filename<256>;

union message switch (tagtype tag) {
    case GET:
        filename filenamedata<2>;
    case OK:
        struct file fdata<2>;
    case QUIT:
        void;
    case ERR:
        void;
};

感谢您阅读本文,并试图理解这一点。我真的很感激。

谢谢!

1 个答案:

答案 0 :(得分:0)

要回答这个问题,我们可以更轻松地查看rpcgen从.x文件生成的类型:tagtypefilefilenamemessage。它们位于您未在问题中包含的xdr_types.h中,因此我将rpcgen与您的.x文件一起使用。重要的是filemessage

...

struct file {
   struct {
      u_int contents_len;
      char *contents_val;
   } contents;
   u_int last_mod_time;
};
typedef struct file file;

typedef char *filename;

struct message {
   tagtype tag;
   union {
      struct {
         u_int filenamedata_len;
         filename *filenamedata_val;
      } filenamedata;
      struct {
         u_int fdata_len;
         struct file *fdata_val;
      } fdata;
   } message_u;
};
typedef struct message message;

...

回答你的两个问题:

  

如果我只需要在邮件中发送一个文件,我会这样做:

response.message_u.fdata.last_mod_time         = last_modification;
response.message_u.fdata.contents.contents_len = file_size;
response.message_u.fdata.contents.contents_val = buffer;
     

缓冲区为:

buffer = malloc(file_size * sizeof(char));

  

另一个问题是如何引用每个文件结构:

response.message_u.fdata[0]                        //?
response.message_u.fdata.last_mod_time[0]          //?
response.message_u.fdata[0].last_mod_time          //?
response.message_u.fdata.contents.contents_len[0]  //?
response.message_u.fdata.contents.contents_val[0]  //?

不,response.message_u.fdata.之后的部分是错误的。它可以是:

response.message_u.fdata.fdata_len

response.message_u.fdata.fdata_val

你的意思是第二个变体是struct file *fdata_val;。对于那部分,你必须分配内存。

以下示例适用于2个文件,这些文件也将回答有关如何引用数据的问题:

// Set variables and allocate space for 2 file structures
message response;
u_int no_files      = 2;
u_int file_size     = 1024;
u_int last_mod_time = 42;
response.message_u.fdata.fdata_len = no_files;
response.message_u.fdata.fdata_val = malloc(no_files * sizeof(struct file));

// Access 1st file and allocate space for file content
response.message_u.fdata.fdata_val[0].last_mod_time         = last_modification;
response.message_u.fdata.fdata_val[0].contents.contents_len = file_size;
response.message_u.fdata.fdata_val[0].contents.contents_val = malloc(file_size * sizeof(char));

// Access 2nd file and allocate space for file content
response.message_u.fdata.fdata_val[1].last_mod_time         = last_modification;
response.message_u.fdata.fdata_val[1].contents.contents_len = file_size;
response.message_u.fdata.fdata_val[1].contents.contents_val = malloc(file_size * sizeof(char));

要了解有关XDR规范语言与生成的C输出之间关系的更多信息,请在SO:Understanding XDR specification to create a *.x file上获得此答案。

此外还有一本很好的书Power Programming with RPC by John Bloomer,它已经很老了(1991),但远程过程调用协议也是如此。本书是关于使用XDR发送/接收数据的RPC协议。 XDR语言(使用rpcgen,过滤函数等)在该书中有很好的描述。

  

以下是一些XDR规范:

     

xdr specification language taken from link provided above