2017-09-06 52 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)。 –