分散システム 電子・情報工学系 新城 靖 <yas@is.tsukuba.ac.jp>
このページは、次の URL にあります。
http://www.hlla.is.tsukuba.ac.jp/~yas/coins/dsys-1998/1999-01-26
/sunrpc-types.html
あるいは、次のページから手繰っていくこともできます。
http://www.hlla.is.tsukuba.ac.jp/~yas/coins/
http://www.hlla.is.tsukuba.ac.jp/~yas/index-j.html
RPCのインタフェースの定義では、定数を記述することができます。
const LSIZE = 80 ;これは、
rpcgen
により、C言語のプリプロセッサのマクロ
#define
に置き換えられます。
RPCのインタフェースの定義では、配列を定義することができる。配列には、
固定長と可変長の2種類あり、固定長は、C言語と同じ。可変長は、次のよう
に[]
の代わりに<>
とする。
int varray<>;
<>
の中には、最大長を書くこともできる。これは、
rpcgen
により、次のような構造体に置き換えられる。
struct { u_int varray_len; int *varray_val; } varray; typedef struct varray varray ;C言語でプログラムを作成する時には、この
varray_len
に要素数を、
varray_val
に、配列の先頭のポインタをセットする。
int a1[10] ; varray v1 ; v1.varray_len = 10 ; v1.varray_val = &a1[0] ;文字列を送るには、特殊な
string
型を使う。
string s<> ;これは、C言語では、
char *
になるが、文字列のつもりで次のよう
に書いても、文字列は送られない。
char *s ;これも、
rpcgen
により、やはり char *
にコンパイルされる
が、この場合、ポインタの先の1文字しか送られない。C言語の文字列を送り
たい時には、必ず string
を使うこと。
SunRPC ではポインタ型も送ること ができるが、ポインタの先の1要素しか送られない。 複数要素を送りいた時には、配列を使う。
C言語の main の引数と同様の構造を送りたい時には、次のようにする。
typedef string argstr_t<>; typedef argstr_t argvt<>;大量のデータをそのまま送るには、
opaque
型
(
不定形型
)
を使う。これには固定長と可変長がある。
opaque fileblock[512] ; opaque filedata<> ;
opaque
の代わりにchar
の配列にすると、文字と見なして1
文字1文字変換が行なわれることになり、非常に遅くなる。場合によっては文
字コードの変換が行なわれる。opaque
では、そのような変換は一切
行なわれず、そのままの形で送られる。
RPCのインタフェースの定義では、共用体(可変長の構造体)が書ける。
union int_result_t switch( int status ) { case OK: int data ; default: void; };これは、次のようにコンパイルされる。
struct int_result_t { int status; union { int data; } int_result_t_u; };
status
という値がOK
の時だけdata
が有効になる。
すなわち、その時だけ実際にネットワークにたいしてdata
の部分が
送られる。
RPCのインタフェースの定義では、
bool_t
という型が使える。値は、
TRUE
か FALSE
。
date.x: ---------------------------------------------------------------------- 1: 2: /* 3: date.x -- 日付時刻サービス 4: このファイルは、次の場所にあります。 5: ~yas/dsys/rpc-date/date.x 6: cp コマンドでコピーできます。 7: $Header: /home/lab2/OS/yas/dsys/rpc-date/RCS/date.x,v 1.4 1999/01/25 18:00:46 yas Exp $ 8: Start: 1999/01/26 02:16:33 9: */ 10: 11: struct ds_timeval 12: { 13: long clock ; 14: }; 15: 16: struct ds_datestr 17: { 18: string str<> ; 19: }; 20: 21: program DATE_PROG { 22: version DATE_VERSION { 23: ds_timeval GETTIMEVAL(void) = 11 ; 24: ds_datestr GETDATESTR(void) = 12 ; 25: } = 1 ; 26: } = 0x20001002 ; ----------------------------------------------------------------------string1つでも構造体にした方がわかりやすい。
date_server.c: ---------------------------------------------------------------------- 1: 2: /* 3: date_server.x -- 日付時刻サービス/サーバ側の手続き 4: このファイルは、次の場所にあります。 5: ~yas/dsys/rpc-date/date_server.c 6: cp コマンドでコピーできます。 7: $Header: /home/lab2/OS/yas/dsys/rpc-date/RCS/date_server.c,v 1.3 1999/01/25 17:59:03 yas Exp $ 8: Start: 1999/01/26 02:16:33 9: */ 10: 11: #include <rpc/rpc.h> 12: #include "date.h" 13: 14: ds_timeval * 15: gettimeval_1() 16: { 17: static ds_timeval res ; 18: res.clock = time( 0 ); /* BSD: gettimeofday() */ 19: return( &res ); 20: } 21: 22: ds_datestr * 23: getdatestr_1() 24: { 25: static ds_datestr res ; 26: char buf[100] ; 27: time_t now ; 28: struct tm *tm_now ; 29: int len ; 30: if( res.str ) 31: { 32: free( res.str ); 33: res.str = 0 ; 34: } 35: now = time( 0 ); 36: tm_now = localtime( &now ); 37: len = strftime( buf, 100, "%a %b %d %H:%M:%S %Z %Y", tm_now ); 38: if( len == 0 ) 39: return( 0 ); 40: res.str = (char *)malloc( len+1 ); 41: if( res.str == 0 ) 42: return( 0 ); 43: strncpy( res.str, buf, len ); 44: res.str[len] = 0 ; 45: return( &res ); 46: } ----------------------------------------------------------------------malloc() してリターンして、次に回って来た時に free() する。
date_client.c ---------------------------------------------------------------------- 1: 2: /* 3: date_server.x -- 日付時刻サービス/クライアント側の手続き 4: このファイルは、次の場所にあります。 5: ~yas/dsys/rpc-date/date_server.c 6: cp コマンドでコピーできます。 7: $Header: /home/lab2/OS/yas/dsys/rpc-date/RCS/date_client.c,v 1.3 1999/01/25 17:59:03 yas Exp $ 8: Start: 1999/01/26 02:16:33 9: */ 10: 11: #include <stdio.h> 12: #include <rpc/rpc.h> 13: #include "date.h" 14: 15: main( int argc, char *argv[] ) 16: { 17: CLIENT *cl; 18: char dummy ; 19: ds_datestr *result ; 20: char *server_name; 21: 22: if( argc != 2 ) { 23: fprintf(stderr, "usage: %s server\n", argv[0]); 24: exit(1); 25: } 26: server_name = argv[1]; 27: cl = clnt_create( server_name, DATE_PROG, DATE_VERSION, "tcp" ); 28: if( cl == NULL ) { 29: clnt_pcreateerror( server_name ); 30: exit( 1 ); 31: } 32: result = getdatestr_1( &dummy, cl ); 33: if( result == NULL ) { 34: clnt_perror( cl, server_name ); 35: exit( 1 ); 36: } 37: printf("getdatestr() returns %s \n", 38: result->str ); 39: xdr_free( xdr_ds_datestr, (char *)result ); 40: } ----------------------------------------------------------------------
% makerpcgen date.x cc -g -c date_client.c -o date_client.o cc -g -c date_clnt.c -o date_clnt.o cc -g -c date_xdr.c -o date_xdr.o cc -o date_client date_client.o date_clnt.o date_xdr.o cc -g -c date_server.c -o date_server.o cc -g -c date_svc.c -o date_svc.o cc -o date_server date_server.o date_svc.o date_xdr.o %
![]()
サーバ側は止まらないので、止めたい時には、% ./date_server![]()
^C
を押す。
ホスト名には、localhost が便利。
% ./date_client localhostgetdatestr() returns Tue Jan 26 03:05:24 JST 1999 %
![]()
Sunの技術で、構造体をファイルに保存することができる。
構造体を整列化し、他のプロセスに通信メッセージとして送る代わりにファイ ルに保存する。
SunRPCでは、xdrstdio_create() という関数が用意されています。 ストリーム入出力(FILE *) に対して構造体を読み書きすることができるようになる。
RPCと同様に、構造体にポインタが含まれていた場合、再帰的にファイルに保 存される。異なる機種で読み出すことができる。