2017-09-06 48 views
0

我希望这个案例能够得到一些帮助。如何从.x文件(内存分配)使用生成的XDR结构

我需要发送一个XDR消息,即它是由2个文件组成开关的情况下== OK)。

假设我有我的代码message对象调用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)); 

现在,我明白了struct file fdata<2>;我t是一个可变大小的数组(2是最大长度),我将它们索引为something[0]something[1]

另外我知道我需要分配内存,但我不知道如何做到这一点在这种情况下与多个文件。

我需要为我需要发送的所有东西做一个单独的malloc吗?事情是这样的:

response.message_u.fdata.fdata_val = malloc ((file_size1 * sizeof(char)) + (file_size2 * sizeof(char)) + (2 * sizeof(uint32_t))); 

(2 * sizeof(uint32_t)):一个last_mod_time为每个文件发送

而其他的问题,我如何引用每个文件结构:

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] //? 

的.X文件:

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; 
}; 

The types.c(用rpcgen生成):

#include "xdr_types.h" 

bool_t 
xdr_tagtype (XDR *xdrs, tagtype *objp) 
{ 
    register int32_t *buf; 

    if (!xdr_enum (xdrs, (enum_t *) objp)) 
     return FALSE; 
    return TRUE; 
} 

bool_t 
xdr_file (XDR *xdrs, file *objp) 
{ 
    register int32_t *buf; 

    if (!xdr_bytes (xdrs, (char **)&objp->contents.contents_val, (u_int *) &objp->contents.contents_len, ~0)) 
     return FALSE; 
    if (!xdr_u_int (xdrs, &objp->last_mod_time)) 
     return FALSE; 
    return TRUE; 
} 


bool_t 
xdr_filename (XDR *xdrs, filename *objp) 
{ 
    register int32_t *buf; 

    if (!xdr_string (xdrs, objp, 256)) 
     return FALSE; 
    return TRUE; 
} 

bool_t 
xdr_message (XDR *xdrs, message *objp) 
{ 
    register int32_t *buf; 

    if (!xdr_tagtype (xdrs, &objp->tag)) 
     return FALSE; 

    switch (objp->tag) { 
     case GET: 
      if (!xdr_array (xdrs, (char **)&objp->message_u.filenamedata.filenamedata_val, (u_int *) &objp->message_u.filenamedata.filenamedata_len, 10, 
      sizeof (filename), (xdrproc_t) xdr_filename)) 
      return FALSE; 
      break; 
     case OK: 
      if (!xdr_array (xdrs, (char **)&objp->message_u.fdata.fdata_val, (u_int *) &objp->message_u.fdata.fdata_len, 10, sizeof (file), (xdrproc_t) xdr_file)) 
      return FALSE; 
      break; 
     case QUIT: 
      break; 
     case ERR: 
      break; 
     default: 
      return FALSE; 
    } 
    return TRUE; 
} 

感谢您阅读本文,并试图理解本文。对此,我真的非常感激。

谢谢!

+0

什么问题你有?什么是问题?它只是关于'malloc'的东西吗?还有别的吗?更多的东西? –

+0

@Someprogrammerdude你好,这实际上是关于如何填写回复消息。如何把数据:东西[0] =数据和东西[1] =数据,但我不知道这样做。正如我在帖子中所说的,我只知道如何使用一个而不是2。 – JoannaM

+1

@wildplasser:不,但它是rpcgen为了使用XDR而生成过滤器函数('xdr_typename()')所需的语言正如OP的cleary所说的那样。有关[.x文件请参阅此处](https://stackoverflow.com/a/26625494/8051589)的更多信息。 –

回答

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

+0

@JoannaM:这个答案对你有帮助吗?您还有其它问题么? –

+0

是的,它做到了!谢谢。我很感激你花时间。我确实需要检查.h生成的文件,并且还读了一些关于xdr的信息。你建议的帖子也有很大帮助。 – JoannaM

+0

@JoannaM:我在回答中添加了一本书中的链接,我认为这对潜入XDR很有帮助:[用John Bloomer的RPC进行电源编程](https://www.amazon.com/dp/0937175773/ ?标签= stackoverfl08-20)。 –