7.4.1 XATMIインタフェースの例

<この項の構成>
(1) リクエスト/レスポンス型サービスの通信の例
(2) 会話型サービスの通信の例

(1) リクエスト/レスポンス型サービスの通信の例

(a) 処理の概要

ここで示す例題の処理概要を,次に説明します。

[説明]宿泊施設の空き状況を調べるサービスと,飛行機の空き状況を調べるサービスを,SUPから呼びます。前者は非同期に,後者は同期的に応答を受信します。

(b) UAPの構成

例題のUAPの構成を次の図に示します。

図7-4 同期的に応答を受信するリクエスト/レスポンス型サービスの通信形態

[図データ]

(c) 通信に使う型付きバッファ

通信に使う型付きバッファの構造体を次に示します。

struct hotel {                   struct plane {
   DCLONG date;                     DCLONG date;
   char place[128];                 char dest[128];
   char hname[128];                 DCLONG departure;
   DCLONG status;                   DCLONG status;
}                                }

(d) SUPの例

 10  /* SUPのXATMIインタフェース定義の例(rrsup.defファイル)*/
 20  called_servers = { "rrspp.def" };

 10  /* SUPの例(rrsup.cファイル)*/
 20  #include <stdio.h>
 30  #include <dcrpc.h>
 40  #include <xatmi.h>
 50  #include <dcadm.h>
 60  /*
 70   * XATMIスタブヘッダファイル
 80   */
 90  #include "rrsup_stbx.h"
100  main()
110  {
120  /*
130   * 変数の定義
140   */
150    struct hotel *hptr;
160    struct plane *pptr;
170    struct  errmsg *werrmsg ;
180    long  hlen, plen ;
190    int  cd ;
200    int rc;
210  /*
220   * RPC-OPEN(UAPの開始)
230   */
240      rc = dc_rpc_open(DCNOFLAGS);
250      if(rc != DC_OK){
260          printf("dc_rpc_openに失敗しました。¥
270                  ERROR CODE = %d ¥n", rc);
280          goto PROG_END;
290      }
300  /*
310   * ADM-COMPLETE(ユーザサーバの開始処理完了の報告)
320   */
330      rc = dc_adm_complete(DCNOFLAGS);
340      if(rc != DC_OK){
350          printf("dc_adm_completeに失敗しました。¥
360                  ERROR CODE = %d ¥n",  rc);
370          goto PROG_END;
380      }
390  /*
400   * TPALLOC(型付きバッファの確保)
410   */
420    /* 宿泊施設空き状況検索サービス用 */
430      hptr = (struct hotel *)tpalloc("X_COMMON", "hotel", 0);
440      if(hptr == NULL){
450          printf("tpallocに失敗しました。¥
460                  ERROR CODE = %d ¥n", tperrno);
470          goto PROG_END;
480      }
490    /* 飛行機空き状況検索サービス用 */
500      pptr = (struct plane *)tpalloc("X_COMMON", "plane", 0);
510      if(pptr == NULL){
520          printf("tpallocに失敗しました。¥
530                  ERROR CODE = %d ¥n", tperrno);
540          goto PROG_END;
550      }
560  /*
570   * データの設定
580   */
590    hptr->date = 940415 ;
600    strcpy(hptr->place, "SAPPORO") ;
610    strcpy(hptr->hname, "PRINCE") ;
620    hptr->status = 0 ;
630    pptr->date = 940415 ;
640    strcpy(pptr->dest, "CHITOSE") ;
650    pptr->departure = 1540 ;
660    pptr->status = 0 ;
670  /*
680   * TPACALL(サービスリクエストを送信する)
690   */
700      cd = tpacall("SVHOTEL", (char *) hptr, 0, 0);
710      if(cd == -1){
720         printf("宿泊施設空状況検索サービスの呼び出しに失敗しました。¥
730                 ERROR CODE = %d ¥n", tperrno);
740         goto PROG_END;
750      }
760      printf("宿泊施設空状況検索サービスの呼び出しに成功しました。¥n");
770  /*
780   * TPCALL(サービスリクエストを送信して,応答を待つ)
790   */
800      rc = tpcall("SVPLANE", (char *) pptr, 0, (char **) &pptr, &plen, 0);
810      if(rc != 0){
820          if(tperrno == TPESVCFAIL){
830             werrmsg = (struct errmsg *) pptr ;
840             printf("%s ERROR CODE = %d USER CODE = %d¥n",
850                     werrmsg->errmessage, tperrno, tpurcode);
860             goto PROG_END ;
870          }else{
880             printf("飛行機空き状況検索サービスの呼び出しに失敗しました。 ¥
890                     ERROR CODE = %d", tperrno);
900             goto PROG_END;
910          }
920      }
930      printf("飛行機空き状況検索サービスの呼び出しの応答受信に成功しました。¥n");
940      if(pptr->status == 1){
950          printf("飛行機空き状況 : 満席です。 ¥n");
960      } else {
970          printf("飛行機空き状況 : 空席があります。 ¥n");
980      }
990  /*
1000   * TPGETRPLY(応答を受信する)
1010   */
1020      rc = tpgetrply(&cd, (char **) &hptr, &hlen, 0);
1030      if(rc != 0){
1040          if(tperrno == TPESVCFAIL){
1050             werrmsg = (struct errmsg *) hptr ;
1060             printf("%s ERROR CODE = %d USER CODE = %d¥n",
1070                     werrmsg->errmessage, tperrno, tpurcode);
1080             goto PROG_END ;
1090          }else{
1100             printf("宿泊施設空状況検索サービスに失敗しました。 ¥
1110                     ERROR CODE = %d", tperrno);
1120             goto PROG_END;
1130          }
1140      }
1150      printf("宿泊施設空状況検索サービスの応答受信に成功しました。¥n");
1160      if(hptr->status == 1){
1170          printf("宿泊施設空き状況 : 満室です。 ¥n");
1180      } else {
1190          printf("宿泊施設空き状況 : 空室があります。 ¥n");
1200      }
1210  /*
1220   * 型付きバッファの解放
1230   */
1240      tpfree((char *) hptr);
1250      tpfree((char *) pptr);
1260  /*
1270   * RPC-CLOSE(UAPの終了)
1280   */
1290      PROG_END:
1300      dc_rpc_close(DCNOFLAGS);
1310      printf("またのご利用をお待ちしています。¥n");
1320      exit(0);
1330  }

 10  #ユーザサービス定義の例(rrsupファイル)
 20  set  module              = "rrsup"
 30  set  receive_from        = none
 40  set  trn_expiration_time = 180
 50  set  trn_expiration_time_suspend = Y

(e) SPPの例

 10  /* XATMIインタフェース定義の例(rrspp.defファイル)*/
 20  X_COMMON hotel {
 30      long   date;
 40      char   place[128];
 50      char   hname[128];
 60      long   status;
 70  };
 80  X_COMMON plane {
 90      long   date;
100      char   dest[128];
110      long   departure;
120      long   status;
130  };
140  X_COMMON errmsg {
150      char   errmessage[128];
160  };
170  service shotel(X_COMMON hotel) ;
180  service splane(X_COMMON plane) ;

 10  /* SPPのメイン関数例(rrspp.cファイル)*/
 20  #include <stdio.h>
 30  #include <dcrpc.h>
 40  #include <xatmi.h>
 50  #include <dcadm.h>
 60  /*
 70   * XATMIスタブヘッダファイル
 80   */
 90  #include "rrspp_stbx.h"
100  main()
110  {
120  /*
130   * 変数の定義
140   */
150     int rc;
160  /*
170   * RPC-OPEN(UAPの開始)
180   */
190      rc = dc_rpc_open(DCNOFLAGS);
200      if(rc != DC_OK){
210          printf("dc_rpc_openに失敗しました。¥
220                  ERROR CODE = %d ¥n", rc);
230          goto PROG_END;
240      }
250  /*
260   * RPC-MAINLOOP(SPPのサービス開始)
270   */
280      rc = dc_rpc_mainloop(DCNOFLAGS);
290      if(rc != DC_OK){
300          printf("dc_rpc_mainloopに失敗しました。¥
310                  ERROR CODE = %d ¥n", rc);
320      }
330  /*
340   * RPC-CLOSE(UAPの終了)
350   */
360  PROG_END:
370      dc_rpc_close(DCNOFLAGS);
380      exit(0);
390  }

 10  /* SPPのサービス関数例(rrsvc.cファイル)*/
 20  #include <stdio.h>
 30  #include <dcrpc.h>
 40  #include <xatmi.h>
 50  #include <dcadm.h>
 60  /*
 70   * XATMIスタブヘッダファイル
 80   */
 90  #include "rrspp_stbx.h"
100  void shotel(svcinfo)
110  TPSVCINFO *svcinfo;
120  {
130  /*
140   * 変数の定義
150   */
160      struct hotel *hptr;
170    
180      hptr = (struct hotel *) svcinfo->data;
190      /* このサービスは空き状況を検索して,満室ならば status = 1 ,
200       * 空室があれば status = 0,エラーが起こったときは,メッセージを返します。
210       * ここでは,検索した結果,満室だったとします。*/
220      hptr->status = 1 ;
230      tpreturn(TPSUCCESS, 0, hptr, 0, 0);
240      return ; /* OpenTP1の場合はtpreturn後にreturnの発行が必要です。 */
250  }
260  void splane(svcinfo)
270  TPSVCINFO *svcinfo;
280  {
290      struct plane *pptr;
300      pptr = (struct plane *) svcinfo->data;
310      /* このサービスは空き状況を検索して,満席ならば status = 1,
320       * 空席があれば status = 0 ,エラーが起こったときは,メッセージを返します。
330       * ここでは,検索した結果,満席だったとします。*/
340      pptr->status = 1 ;
350      tpreturn(TPSUCCESS, 0, pptr, 0, 0);
360      return ;
370  }

 10  #ユーザサービス定義の例(rrsppファイル)
 20  set    service_group      = "rrspp_svg"
 30  set    module             = "rrspp"
 40  set    service            = "SVHOTEL=shotel","SVPLANE=splane"
 50  set    trn_expiration_time = 180
 60  set    trn_expiration_time_suspend = Y
 70  set    server_type = "xatmi"

(2) 会話型サービスの通信の例

(a) 処理の概要

ここで示す例題の処理概要を,次に説明します。

[説明]acctreq構造体の構造を持つ型付きバッファでサービス関数を起動します。acctreqのメンバは口座番号の上限と下限を示します。サービス関数では,この範囲にある口座データをacctdat構造体の構造を持つ型付きバッファに設定して,会話のオリジネータに送信します。

(b) UAPの構成

例題のUAPの構成を次の図に示します。

図7-5 会話型サービスの通信形態

[図データ]

(c) 通信に使う型付きバッファ

通信に使う型付きバッファの構造体を次に示します。

(d) SUPの例

 10  /* SUPのXATMIインタフェース定義の例(convsup.defファイル)*/
 20  called_servers = { "convspp.def" };

 10  /* SUPのコーディング例(convsup.cファイル)*/
 20  #include <stdio.h>
 30  #include <dcrpc.h>
 40  #include <xatmi.h>
 50  #include <tx.h>
 60  #include <dcadm.h>
 70  /*
 80   * XATMIスタブヘッダファイル
 90   */
100  #include "convsup_stbx.h"
110  main()
120  {
130  /*
140   * 変数の定義
150   */
160      struct   acctreq  *rptr;
170      struct   acctdata *dptr;
180      long     wlen;
190      int      cd;
200      int      rc;
210      long     revent;
220      long     size = 0 ;
230  /*
240   * RPC-OPEN(UAPの開始)
250   */
260      rc = dc_rpc_open(DCNOFLAGS);
270      if(rc != DC_OK){
280          printf("dc_rpc_openに失敗しました。ERROR CODE = %d ¥n", rc);
290          goto PROG_END;
300      }
310  /*
320   * ADM-COMPLETE(ユーザサーバの開始処理完了の報告)
330   */
340      rc = dc_adm_complete(DCNOFLAGS);
350      if(rc != DC_OK){
360          printf("dc_adm_completeに失敗しました。ERROR CODE = %d ¥n", rc);
370          goto PROG_END;
380      }
390  /*
400   * TPALLOC(型付きバッファの確保)
410   */
420    /*サーチする口座番号の上限,下限の設定用*/  
430      rptr = (struct acctreq *)tpalloc(X_COMMON, "acctreq", 0);
440  
450      if(rptr == NULL){
460          printf("tpallocに失敗しました。ERROR CODE = %d ¥n", tperrno);
470          goto PROG_END;
480      }
490    /*サーチ結果の口座データ用*/  
500      dptr = (struct acctdata *)tpalloc(X_COMMON, "acctdata", 0) ;
510      if(dptr == NULL){
520          printf("tpallocに失敗しました。ERROR CODE = %d ¥n", tperrno);
530          goto PROG_END;
540      }
550  /*
560   * データの設定
570   * サーチする範囲を指定
580   */
590      rptr->lower_no = 10000000L;
600      rptr->upper_no = 20000000L;
610   /* トランザクション開始  */
620      tx_begin() ;
630  /*
640   * TPCONNECT(会話サービスの呼び出し)
650   * INQUIRYを呼ぶ。
660   */
670      cd = tpconnect("INQUIRY", (char *) rptr, 0, TPRECVONLY);
680      if(cd == -1){
690          printf("tpconnectに失敗しました。ERROR CODE = %d ¥n", tperrno);
700          goto PROG_END;
710      }
720  /*
730   * エラーが起こるまで(イベントの発生も含む),
740   * TPRECV(メッセージを受信)
750   */
760      while(rc != -1){
770          rc = tprecv(cd, (char **) &dptr, &wlen, 0, &revent);
780          /*
790           *エラーが起こっていなければ,
800           *受信した口座情報を出力する。
810           */
820          if(rc != -1) {
830              printf("サービスから口座情報を受信しました。¥n");
840              printf("口座番号 = %d ¥n", dptr->acct_no);
850              printf("名前 = %s ¥n", dptr->name);
860              printf("預金 = %d ¥n", dptr->amount);
870          }
880      }
890  /*
900   * サービスの結果の出力
910   */
920      if(tperrno == TPEEVENT){
930          if(revent == TPEV_SVCSUCC){
940          /* サービスは成功した。*/
950              printf("サービスは成功しました。¥n");
960              /* トランザクションのコミット */
970              tx_commit() ;
980          }else{
990              printf("何らかのイベントが発生しています。revent = %d¥n",
1000              revent);
1010              /* トランザクションのロールバック*/
1020              tx_rollback() ;
1030          }
1040    }
1050  /*
1060   * 型付きバッファの解放
1070   */
1080      tpfree((char *) rptr);
1090      tpfree((char *) dptr);
1100  /*
1110   * RPC-CLOSE(UAPの終了)
1120   */
1130      PROG_END:
1140      dc_rpc_close(DCNOFLAGS);
1150      exit(0);
1160  }

 10  #ユーザサービス定義の例(convsupファイル)
 20  set module              = "convsup"         #実行形式ファイル名
 30  set watch_time          = 180               #最大応答待ち時間
 40  set receive_from        = none              #受信方法
 50  set trn_expiration_time = 180
 60                              #トランザクションブランチ限界経過時間
 70  set trn_expiration_time_suspend = Y         #必ず Y を指定

(e) SPPの例

 10  /* SPPのXATMIインタフェース定義の例(convspp.defファイル)*/
 20  X_COMMON acctreq {
 30      long   upper_no;
 40      long   lower_no;
 50  };
 60  X_COMMON acctdata {
 70      long   acct_no;
 80      char   name[128];
 90      short  amount;
100  };
110  service inquiry(X_COMMON acctreq) ;

 10  /* SPPのメイン関数例(convspp.cファイル)*/
 20  #include <stdio.h>
 30  #include <dcrpc.h>
 40  #include <xatmi.h>
 50  #include <dcadm.h>
 60  /*
 70   * XATMIスタブヘッダファイル
 80   */
 90  #include "convspp_stbx.h"
100  main()
110  {
120  /*
130   * 変数の定義
140   */
150      int rc;
160  /*
170   * RPC-OPEN(UAPの開始)
180   */
190      rc = dc_rpc_open(DCNOFLAGS);
200      if(rc != DC_OK){
210          printf("dc_rpc_openに失敗しました。ERROR CODE = %d ¥n", rc);
220          goto PROG_END;
230      }
240    
250  /*
260   * RPC-MAINLOOP(SPPのサービス開始)
270   */
280      rc = dc_rpc_mainloop(DCNOFLAGS);
290      if(rc != DC_OK){
300          printf("dc_rpc_mainloopに失敗しました。ERROR CODE = %d ¥n",rc);
310      }
320  /*
330   * RPC-CLOSE(UAPの終了)
340   */
350      PROG_END:
360      dc_rpc_close(DCNOFLAGS);
370      exit(0);
380  }

 10  /* SPPのサービス関数例(convsvc.cファイル)*/
 20  #include <stdio.h>
 30  #include <dcrpc.h>
 40  #include <xatmi.h>
 50  #include <dcadm.h>
 60  /*
 70   * XATMIスタブヘッダファイル
 80   */
 90  #include "convspp_stbx.h"
100  /*
110   * DEPOSITSVC  サービス関数
120   * tpconnect()によって口座番号の上限,下限を受取り
130   * その範囲にある口座の情報を送信する。
140   */
150  void inquiry(svcinfo)
160  TPSVCINFO *svcinfo;
170  {
180  /*
190   * 変数の定義
200   */
210      struct   acctreq  *rptr;
220      struct   acctdata *dptr;
230      char     type[9];
240      char     subtype[17];
250      long     revent, rval;
260      int      size;
270  /*
280   * サービス要求が受け付けられた
290   */
300      rptr = (struct acctreq *) svcinfo->data;
310  /*
320   * オリジネータに返すデータのtypedバッファの確保
330   */
340      dptr = (struct acctdata *)tpalloc("X_COMMON", "acctdata", 0);
350      if(dptr == NULL){
360          printf("tpallocでエラーが起こりました。tperrno = %d ¥n",
370                 tperrno);
380          abort();
390      }
400  /*
410   * ユーザ処理
420   * データファイルを検索して口座番号が範囲内の口座情報を返す。
430   * ここでは2件見つかったこととしてデータを送信する。
440   */
450      
460      dptr->acct_no = 10000001L;
470      strcpy(dptr->name, "Hitachi Hanako");
480      dptr->amount = 20000;
490  /*
500   * TPSEND(メッセージの送信)
510   */
520      tpsend(svcinfo->cd, (char *) dptr, 0, 0, &revent);
530      if(tperrno != -1){
540          rval = TPSUCCESS;
550      }else{
560          rval = TPFAIL;
570          goto SVC_END;
580      }
590      dptr->acct_no = 10000002L;
600      dptr->amount = 10000;
610      strcpy(dptr->name, "Hitachi Tarou");
620  /*
630   * TPSEND(メッセージの送信)
640   */
650      tpsend(svcinfo->cd, (char *) dptr, 0, 0, &revent);
660      if(tperrno != -1){
670          rval = TPSUCCESS;
680      }else{
690          rval = TPFAIL;
700          goto SVC_END;
710      }
720  SVC_END:
730      tpreturn(rval, 0, NULL, 0, 0);
740      return; /* OpenTP1の場合 tpreturn後にreturnが必要です。*/
750  }

 10  # ユーザサービス定義の例(convsppファイル)
 20    set  service_group     = "convspp_svg"     #サービスグループ名
 30    set  module            = "convspp"         #実行形式ファイル名
 40    set  service  = "INQUIRY=inquiry"
 50                              #サービス名=エントリポイント名
 60    set  watch_time        = 180               #最大応答待ち時間
 70    set  trn_expiration_time = 240
 80                              #トランザクションブランチ限界経過時間
 90    set  trn_expiration_time_suspend = Y       #必ず Y を指定
100    set  server_type = "xatmi"                 #サーバタイプ
110    set  receive_from = "socket"               #受信方法