SunRPC で使えるデータ型

分散システム

                                       電子・情報工学系
                                       新城 靖
                                       <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

■SunRPC で使えるデータ型

RPCのインタフェースで使えるデータ構造は、C言語とほぼ同じですが、可変 長のデータが扱えるよう拡張されてる部分や、制限されている部分がある。

★ベクトルの加減サービス

◆基本型

int (32ビット), unsigned, char, long, float, double

◆列挙型

ほぼC言語と同等に書けますが、 自動的に typedef されます。 自動的に typedef されます。

◆構造体

ほぼC言語と同等に書けますが、 自動的に typedef されます。

◆定数

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要素しか送られない。 複数要素を送りいた時には、配列を使う。

◆argv

C言語の main の引数と同様の構造を送りたい時には、次のようにする。

typedef string argstr_t<>; 
typedef argstr_t argvt<>;

◆opaque(不定形)

大量のデータをそのまま送るには、 opaque 型 ( 不定形型 ) を使う。これには固定長と可変長がある。
opaque fileblock[512] ;
opaque filedata<> ;

opaque の代わりにchar の配列にすると、文字と見なして1 文字1文字変換が行なわれることになり、非常に遅くなる。場合によっては文 字コードの変換が行なわれる。opaque では、そのような変換は一切 行なわれず、そのままの形で送られる。

◆union共用体

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 の部分が 送られる。

◆bool_t

RPCのインタフェースの定義では、bool_t という型が使える。値は、 TRUEFALSE

■日付時刻サービス

◆日付時刻サービスのインタフェース


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:	}

----------------------------------------------------------------------

◆コンパイル


% make [←]
rpcgen  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 localhost [←]
getdatestr() returns Tue Jan 26 03:05:24 JST 1999 
% []

■XDRによる構造体のファイルへの保存

Sunの技術で、構造体をファイルに保存することができる。

構造体を整列化し、他のプロセスに通信メッセージとして送る代わりにファイ ルに保存する。

SunRPCでは、xdrstdio_create() という関数が用意されています。 ストリーム入出力(FILE *) に対して構造体を読み書きすることができるようになる。

RPCと同様に、構造体にポインタが含まれていた場合、再帰的にファイルに保 存される。異なる機種で読み出すことができる。


[SunRPC] [SunRPCデータ型] [SunRPC練習問題] [NFS] [Pthread] [Pthread同期]
↑[もどる] ←[1月19日] ・[1月26日] →[2月2日]
Last updated: 1999/02/09 01:18:07
Yasushi Shinjo / <yas@is.tsukuba.ac.jp>