0

我希望得到一些关于这个案子的帮助。

我需要发送一条 XDR 消息,它由2 个文件组成(switch case == 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));

现在,我知道它是一个可变大小的数组(2 是最大长度)并且struct file fdata<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;
}

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

谢谢!

4

1 回答 1

0

tagtype要回答这个问题,看一下rpcgen 从您的 .x 文件生成file的类型会filename更容易一些。message它们位于您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;

...

要回答您的 2 个问题:

如果我只能在消息中发送一个文件,我会这样做:

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 is有用。

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

以下是一些 XDR 规格:

xdr 规范语言取自上面提供的链接

于 2017-09-06T12:38:01.693 回答