如何使用从 .x 文件生成的 XDR 结构(内存分配)
How to use generated XDR structures from .x file (memory allocation)
我想就此案寻求帮助。
我需要发送 一条 XDR 消息,它由 2 个文件 组成(switch case == OK ).
假设我的代码中有一个名为 response
:
的 message
对象
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>;
它是一个可变大小的数组(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;
};
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;
}
感谢您阅读本文并尝试理解这一点。非常感谢。
谢谢!
要回答这个问题,可以更容易地查看类型:rpcgen 从您的 .x 生成的 tagtype
、file
、filename
和 message
文件。它们位于您的 xdr_types.h
中,您没有将其包含在您的问题中,因此我将 rpcgen 与您的 .x 文件一起使用。重要的是 file
和 message
:
...
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;
...
回答您的 2 个问题:
If I had to only send one file in a message, I would do:
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;
With buffer being:
buffer = malloc(file_size * sizeof(char));
和
And the other question how to I refer to each file structure:
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 用于 sending/receiving 数据的 RPC 协议。 XDR 语言(使用 rpcgen、过滤函数等)在那本书中有很好的描述。
Below are some XDR specifications:
我想就此案寻求帮助。
我需要发送 一条 XDR 消息,它由 2 个文件 组成(switch case == OK ).
假设我的代码中有一个名为 response
:
message
对象
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>;
它是一个可变大小的数组(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;
};
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;
}
感谢您阅读本文并尝试理解这一点。非常感谢。
谢谢!
要回答这个问题,可以更容易地查看类型:rpcgen 从您的 .x 生成的 tagtype
、file
、filename
和 message
文件。它们位于您的 xdr_types.h
中,您没有将其包含在您的问题中,因此我将 rpcgen 与您的 .x 文件一起使用。重要的是 file
和 message
:
...
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;
...
回答您的 2 个问题:
If I had to only send one file in a message, I would do:
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;
With buffer being:
buffer = malloc(file_size * sizeof(char));
和
And the other question how to I refer to each file structure:
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 用于 sending/receiving 数据的 RPC 协议。 XDR 语言(使用 rpcgen、过滤函数等)在那本书中有很好的描述。
Below are some XDR specifications: