ここで示す例題の処理概要を,次に説明します。
[説明]宿泊施設の空き状況を調べるサービスと,飛行機の空き状況を調べるサービスを,SUPから呼びます。前者は非同期に,後者は同期的に応答を受信します。
例題のUAPの構成を次の図に示します。
図7-4 同期的に応答を受信するリクエスト/レスポンス型サービスの通信形態
通信に使う型付きバッファの構造体を次に示します。
struct hotel { struct plane {
DCLONG date; DCLONG date;
char place[128]; char dest[128];
char hname[128]; DCLONG departure;
DCLONG status; DCLONG status;
} }
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
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"
ここで示す例題の処理概要を,次に説明します。
[説明]acctreq構造体の構造を持つ型付きバッファでサービス関数を起動します。acctreqのメンバは口座番号の上限と下限を示します。サービス関数では,この範囲にある口座データをacctdat構造体の構造を持つ型付きバッファに設定して,会話のオリジネータに送信します。
例題のUAPの構成を次の図に示します。
図7-5 会話型サービスの通信形態
通信に使う型付きバッファの構造体を次に示します。
struct acctreq{
DCLONG upper_no;
DCLONG lower_no;
}
struct acctdat{
DCLONG acct_no;
char name[128];
short amount;
char dc_dummy0[2];
}
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 を指定
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" #受信方法