2014-12-13 3 views
0

libtirpc 라이브러리를 사용하여 RPC를 통해 배열을 보내는 데 약간 어려움이 있습니다.RPC를 통해 배열을 보내려면 어떻게해야합니까?

// Client-side boilerplate 
struct timeval tout = { 1, 0 }; 
int in = 42; 
clnt_call (cln, 1, (xdrproc_t)xdr_int, (char*)&in, 
    (xdrproc_t)xdr_void, NULL, tout);  

// Server-side boilerplate 
int in; 
svc_getargs (xprt, (xdrproc_t)xdr_int, (char*)&in); 
assert (in == 42); 

xdrproc_t 기능 서명이 bool_t (*xdrproc_t) (XDR *, void *, ...);입니다 : 클라이언트 - 서버 세션 동안 프리미티브 보내기만큼 간단합니다. xdr_int(3), xdr_long(3) 및 기타 프리미티브 시리얼 라이저에는 가변 인수가 없으므로 clnt_call(3)svc_getargs(3) 함수를 사용하여 직접 사용할 수 있습니다.

bool_t xdr_array(XDR *xdrs, char **arrp, unsigned int *sizep, 
       unsigned int maxsize, unsigned int elsize, 
       xdrproc_t elproc); 

clnt_call(3) 정말 너무 래퍼 함수를 ​​생성하는 기능에 이러한 인수를 전달할 수 없습니다 svc_getargs(3) 기능에 가장 깨끗한 해결책처럼 보였다 : 가변 길이 배열을 직렬화하는 데 사용되는 xdr_array(3) 기능은, 그러나, 더 많은 인수를 문제는 :

// Client-side boilerplate 
long a = 1, b = 2; 
long * arr[] = { &a, &b }; 
unsigned int amount = sizeof(arr)/sizeof(long*); 
bool_t xdr_array_wrapper (XDR * xdr, void * ptr) { 
    return xdr_array (xdr, ptr, &amount, amount, 
     sizeof(long), (xdrproc_t)xdr_long); 
} 

struct timeval tout = { 1, 0 }; 
long out; 
clnt_call (cln, 1, (xdrproc_t)xdr_array_wrapper, 
    (char*)arr, (xdrproc_t)xdr_long, (char*)&out, tout); 

// Server-side boilerplate 
long * arr[2]; 
unsigned int amount = sizeof(arr)/sizeof(long*); 
bool_t xdr_array_wrapper (XDR * xdr, void * ptr) { 
    return xdr_array (xdr, ptr, &amount, amount, 
     sizeof(long), (xdrproc_t)xdr_long); 
} 
svc_getargs (xprt, (xdrproc_t)xdr_array_wrapper, (char*)arr); 
long a = *arr[0], b = *arr[1]; 

그러나, 알려지지 않은 이유로, 어레이 (가변 a)의 첫 번째 요소가 전송되고, 다른 하나는 쓰레기를 포함한다. 내가 도대체 ​​뭘 잘못하고있는 겁니까?

답변

2

두 가지 이유로 xdr_array을 잘못 사용하고 있습니다.

  1. 동적으로 할당 된 배열 만 처리 할 수 ​​있습니다.
  2. int*의 배열을 마치 int의 배열 인 것처럼 보내려고합니다.

을 사용하는 올바른 방법은 다음과 같이 간다 (IBM 단순화 도난,보다 완벽한 치료를 위해 링크를 참조) :

typedef struct xarray 
{ 
     int size; 
     int *p_array; 
} xarray ; 

bool_t xdr_xarray(XDR *xdrs, xarray *p_xarray) 
{ 
    return xdr_array(
       xdrs, 
       (char**)(&(p_xarray->p_array)), 
       &(p_xarray->size), 
       MAX_INT, 
       sizeof(int), 
       (xdrproc_t)xdr_int)) 
} 

참고 이러한 thinsg :

  1. p_array은 동적으로 할당 된 배열에 대한 포인터입니다.
  2. 포인터가 아닌 int의 배열입니다.
  3. p_array의 주소를 xdr_array으로 전달하므로 디코딩 할 때 필요한 크기의 배열을 할당하고 p_array에 할당 할 수 있습니다.

고정 크기 배열을 원하면 xdr_vector을 사용해야합니다.

typedef struct xvector 
{ 
     int vector[42]; 
} xarray ; 

bool_t xdr_xvector(XDR *xdrs, xarray *p_xvector) 
{ 
    return xdr_vector(
       xdrs, 
       (char*)p_xvector->vector, 
       42, 
       sizeof(int), 
       (xdrproc_t)xdr_int)) 
} 

여기서도 포인터 배열을 사용하지 마십시오.

RPC 컴파일러는 데이터 구조에서 XDR 프로 시저를 자동으로 생성하므로 사용하는 것이 좋습니다.

+0

감사합니다.'xdr_vector (3)'은 제가 필요로하는 것입니다. 'xdr_array (3)'가'SIGSEGV' 시그널을 다른 프로세스에 전송하게 만들었 기 때문에 나는 일련의 포인터를 사용하여 끝내게되었습니다. 이제는 함수가 배열에 대한 이중 포인터를 필요로했기 때문에 그것을 보았습니다. 나는 그것을 제공하지 않았습니다 ('arr'은'& arr'과 정적으로 연상 된 배열을가집니다). 이 링크는 많은 도움이됩니다. 필자는 맨페이지를 중심으로 코드를 작성했습니다.이 코드는 제가 원했던 것보다 간결합니다. – Witiko