リモートホストのプログラムを呼び出すことができるRPCは古くからありますが、あまり使う機会がありませんでした。セキュリティ面、保守性を考えると比較的使われにくいのは理解できるのですが、Unixの面白い部分でもありますし、プログラムをネットワーク分散実行する際のアイディアにもなりますのて、取り上げてみました。
環境 : Ubuntu 14.04
参考 : http://www.ncad.co.jp/~komata/c-kouza15.htm
RPC以外にも、このサイトにあるC言語講座はとてもわかりやすく書かれていて、とても貴重です。(昔を思い出します) Unixの記述言語としてのCを理解することは、今の時代も有益だと、つくづく感じます。
ソースはこのサイトにあるものを元にしましたが、今の環境だからなのかサーバ側がメモリ解放を二重でやってクラッシュしてしまうので、応急的な修正をしました。
また引数などなつかしいスタイルで書かれているので、これも変更しています。
クライアント側(rpc_clie.c)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
#include<stdio.h> #include<strings.h> #include<rpc/rpc.h> #define BUF_SIZE 8192 #define RLS_PROG ((u_long)0x20000000) #define RLS_VER ((u_long)1) #define RLS_PROC ((u_long)1) int main(int argc, char *argv[]) { char buf[BUF_SIZE]; strcpy(buf,"Client Message"); call_rls("localhost", buf); printf("Response : %s\n",buf); return 0; } bool_t xdr_rls(XDR *xdrs, char *objp) { return(xdr_string(xdrs, &objp, BUF_SIZE)); } int call_rls(char *host, char *buf) { int clnt_stat = callrpc(host, RLS_PROG, RLS_VER, RLS_PROC, (xdrproc_t)xdr_rls, buf, (xdrproc_t)xdr_rls, buf); if(clnt_stat!=0){ clnt_perrno(clnt_stat); } return(0); } |
サーバ側(rpc_serv.c)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
#include <stdio.h> #include <string.h> #include <sys/types.h> #include <rpc/rpc.h> #define BUF_SIZE 8192 #define RLS_PROG ((u_long)0x20000000) #define RLS_VER ((u_long)1) #define RLS_PROC ((u_long)1) char *do_rls(char *buf) { printf("request : %s\n", buf); strcpy(buf, "Server message"); return(buf); } bool_t xdr_rls_in(XDR *xdrs,char *objp) { static int f = 0; if( f >= 1){ f = 0; return 1; } f ++; return(xdr_string(xdrs, &objp, BUF_SIZE)); } bool_t xdr_rls_out(XDR *xdrs,char *objp) { return(xdr_string(xdrs, &objp, BUF_SIZE)); } int main() { registerrpc(RLS_PROG, RLS_VER, RLS_PROC, do_rls, xdr_rls_in, xdr_rls_out); svc_run(); return 0; } |
コマンド
apt-get install rpcbind
cc -o rpc_clie rpc_clie.c
cc -o rpc_serv rpc_serv.c
最初の4つが、サーバ起動時。次の4つがクライアント実行時。(2回分)
rpcbindサービスが起動している必要があります。(sunrpc port:111)