会話型通信はOracle Tuxedoシステムのメッセージ交換のパラダイムで、人の会話に似た通信がATMIクライアントおよびサーバー間で実装されています。この通信方法では、クライアント(イニシエータ)とサーバー(サブオーディネート)間で仮想接続が行われて、双方で会話の状態に関する情報が保持されます。この接続は、接続を終了するイベントが発生するまで継続します。
会話型通信では、クライアントとサーバー間に半二重接続が確立されます。半二重接続では、メッセージが1方向だけに送信されます。接続に関する制御は、イニシエータからサブオーディネートへ、またはその逆に移ります。制御を持つプロセスがメッセージを送信でき、持たないプロセスは受信しかできません。
図7-1の銀行業務のオンライン・アプリケーションを例に、Oracle Tuxedo ATMIアプリケーションで行われる会話型通信について説明します。この例では、銀行の顧客が過去2か月間の当座預金の明細書をリクエストしています。
注: | 口座レコード管理システムでは、状態情報を保持して、顧客がMore プロンプトを選択した場合にどの明細書を送るのか認識できるようにする必要があります。 |
リクエスト/レスポンス型通信の場合と同じように、Oracle Tuxedoシステムでは型付きバッファを使用してデータが渡されます。アプリケーションがバッファ・タイプを認識できることが必要です。バッファ・タイプの詳細は、「型付きバッファの概要」を参照してください。
会話型のクライアントおよびサーバーには、次の特徴があります。
会話型通信は、次の点でリクエスト/レスポンス型通信と異なります。
会話型クライアントは、サービスへの接続を確立する前に、tpinit()を呼び出してアプリケーションに参加する必要があります。詳細は、「クライアントのコーディング」を参照してください。
tpconnect(3c)関数は、会話を行うための接続を確立します。
tpconnect
()関数の呼出しには、次のシグネチャを使用します。
int
tpconnect(char *name
, char *data
, longlen
, longflags
)
表7-1は、tpconnect()
関数の引数を示しています。
データ・バッファを指すポインタ。
data 引数に、tpalloc()を使用してすでに割り当てられているバッファを指すポインタを設定すると、接続の確立と同時にデータを送信することができます。バッファのタイプ とサブタイプ は、呼び出されたサービスで認識できなければなりません。data にNULLを設定して、送信データがないことを示すことができます。
呼び出された会話型サービスは、
TPSVCINFO データ構造体を介してdata およびlen ポインタを受け取ります。この構造体は、サービスが呼び出されたときにmain() 関数によって渡されます。(リクエスト/レスポンス・サービスも同じ方法で、data およびlen ポインタを受け取ります。)TPSVCINFO データ構造体の詳細については、「サービスの定義」を参照してください。
|
|
フラグの設定値。有効なフラグの設定値については『Oracle Tuxedo ATMI C言語関数リファレンス』の「tpconnect(3c)」を参照してください。
|
tpconnect
()によって接続が確立されると、Oracle Tuxedoシステムから接続記述子(cd
)が返されます。このcd
は、特定の会話で以降に送られるメッセージを識別するために使用されます。クライアントまたは会話型サービスは、複数の会話に同時に参加できます。最大64個の会話を同時に行うことができます。
tpconnect
()関数の呼出しが失敗すると-1
が返され、対応するエラー・コードがtperrno
に設定されます。エラー・コードについては、『Oracle Tuxedo ATMI C言語関数リファレンス』の「tpconnect(3c)」を参照してください。
リスト7-1は、tpconnect
()関数の使用方法を示しています。
#include atmi.h
#define FAIL -1
int cd1; /* Connection Descriptor */
main()
{
if ((cd = tpconnect(“AUDITC”,NULL,0,TPSENDONLY)) == -1) {
error routine
}
}
Oracle Tuxedoシステムで会話型接続が確立されると、イニシエータとサブオーディネート間の通信は送信呼出しと受信呼出しを使用して行われます。接続の制御を持つプロセスは、tpsend(3c)関数を使用してメッセージを送信できます。制御がないプロセスは、tprecv(3c)関数を使用してメッセージを受信できます。
注: | 発信元(クライアント)は、最初にtpconnect() 呼出しのTPSENDONLY またはTPRECVONLYフラグを使用して、どのプロセスが制御を持っているのかを判別します。TPSENDONLY は、発信元が制御を持つことを示します。TPRECVONLY は、呼び出されたサービスに制御が渡されたことを示します。 |
メッセージを送信するには、tpsend(3c)関数を使用します。この関数には、次のシグネチャを使用します。
int
tpsend(int cd, char *data, long len, long flags, long *revent)
表7-2は、tpsend
()関数の引数を示しています。
tpconnect()関数で戻され、データが送信される接続を識別する接続記述子。
|
|
データ・バッファを指すポインタ。
data 引数に、tpalloc()を使用してすでに割り当てられているバッファを指すポインタを設定すると、接続の確立と同時にデータを送信することができます。バッファのタイプ とサブタイプ は、呼び出されたサービスで認識できなければなりません。data にNULLを設定して、送信データがないことを示すことができます。
呼び出された会話型サービスは、
TPSVCINFO データ構造体を介してdata およびlen ポインタを受け取ります。この構造体は、サービスが呼び出されたときにmain() 関数によって渡されます。(リクエスト/レスポンス・サーバーも同じ方法で、data およびlen ポインタを受け取ります。)TPSVCINFO データ構造体の詳細については、「サービスの定義」を参照してください。
|
|
エラーの発生時(つまり、tperrno(5)に
TPEEVENT が設定された場合)に、設定されるイベント値を指すポインタ。有効なイベント値については、『Oracle Tuxedo ATMI C言語関数リファレンス』の「tpsend(3c)」を参照してください。
|
|
フラグの設定値。有効なフラグ設定については、『Oracle Tuxedo ATMI C言語関数リファレンス』の「tpsend(3c)」を参照してください。
|
tpsend
()関数の呼出しが失敗すると-1
が返され、対応するエラー・コードがtperrno(5)に設定されます。エラー・コードについては、『Oracle Tuxedo ATMI C言語関数リファレンス』の「tpsend(3c)」を参照してください。
tpsend
()関数を呼び出すたびに、制御を渡す必要はありません。一部のアプリケーションでは、tpsend
()の呼出しを認められているプロセスが、制御をほかのプロセスに渡すまで、現在のタスクで必要な回数だけ呼出しを実行できます。ただし、プログラムのロジックによっては、会話が継続する間は常に1つのプロセスが接続の制御を持たなければならないアプリケーションもあります。
リスト7-2は、tpsend
()関数の呼出し方法を示しています。
if (tpsend(cd,line,0,TPRECVONLY,revent) == -1) {
(void)userlog(“%s: tpsend failed tperrno %d”,
argv[0],tperrno);
(void)tpabort(0);
(void)tpterm();
exit(1);
}
オープン接続を介してデータを受信するには、tprecv(3c)関数を使用します。この関数には、次のシグネチャを使用します。
int
tprecv(intcd
, char **data
, long *len
, longflags
, long *revent
)
接続記述子。従属プログラムで呼出しを行う場合は、
cd 引数に、そのプログラムのTPSVCINFO 構造体に指定されている値を設定します。発信元のプログラムで呼出しを行う場合は、cd 引数に、tpconnect()関数で返される値を設定します。
|
|
データ・バッファを指すポインタ。
data 引数は、tpalloc()を使用して既に割り当てられているバッファを指す必要があります。バッファのタイプ とサブタイプ は、呼び出されたサービスで認識できなければなりません。NULLを指定すると呼出しは失敗し、tperrno(5)にTPEINVAL が設定されます。
呼び出された会話型サービスは、
TPSVCINFO データ構造体を介してdata およびlenポインタを受け取ります。この構造体は、サービスが呼び出されたときにmain() 関数によって渡されます。(リクエスト/レスポンス・サービスも同じ方法で、data およびlen ポインタを受け取ります。)TPSVCINFO データ構造体の詳細については、「サービスの定義」を参照してください。
|
|
エラーの発生時(つまり、
tperrno にTPEEVENT が設定された場合)に、設定されるイベント値を指すポインタ。有効なイベント値については、『Oracle Tuxedo ATMI C言語関数リファレンス』の「tprecv(3c)」を参照してください。
|
|
フラグの設定値。有効なフラグについては、『Oracle Tuxedo ATMI C言語関数リファレンス』の「tprecv(3c)」を参照してください。
|
処理が成功すると、*
data
が受信データを指し、len
にバッファのサイズが格納されます。len
がtprecv
()を呼び出す前のバッファの合計サイズより大きい場合、バッファのサイズは変更されていて、len
はバッファの新しいサイズを示しています。len
引数が0の場合、受信データがないことを示します。
リスト7-3は、tprecv
()関数の使用方法を示しています。
if (tprecv(cd,line,len,TPNOCHANGE,revent) != -1) {
(void)userlog(“%s: tprecv failed tperrno %d revent %ld”,
argv[0],tperrno,revent);
(void)tpabort(0);
(void)tpterm();
exit(1);
}
tpreturn()
の呼出しが成功した場合注: | tpreturn()関数については、「クライアントおよびサーバーへのリクエスト/レスポンスのコーディング」を参照してください。 |
以下の項では、会話を正常に終了する方法について、2つの例を挙げて説明します。これらの会話には、tpreturn()関数を使用するグローバル・トランザクションは含まれていません。
最初の例では、2つのコンポーネント間の単純な会話を終了する方法を示します。2番目の例では、会話が階層構造になっている複雑な会話を終了する方法を示します。
接続がオープンになっているときに会話を終了すると、エラーが返されます。その場合、tpcommit()またはtpreturn()は失敗します。
図7-2は、正常に終了するAとB間の単純な会話を示しています。
TPSENDONLY
フラグでtpconnect()を呼び出して接続を設定します。このフラグは、Bが会話の受信側であることを示します。TPRECVONLY
フラグでtpsend()を呼び出して、接続の制御をBに移します。その結果、TPEV_SENDONLY
イベントが生成されます。TPEEVENT
が設定されてます。revent
引数にTPEV_SENDONLY
が返されて、制御がBに移ったことが示されます。rval
にTPSUCCESS
を設定してtpreturn()を呼び出します。この呼出しにより、Aに対してTPEV_SVCSUCC
イベントが生成され、接続が正常に切断されます。 TPEV_SVCFAIL
が発生した場合でも、このtprecv()
への呼出しでデータを受信できます。 注: | この例では、Aはクライアントまたはサーバーのどちらでもかまいませんが、Bはサーバーでなければなりません。 |
図7-3は、正常に終了する階層構造の会話を示しています。
この例では、サービスBは会話のメンバーで、2番目のサービスCとの接続を開始しています。つまり、A - B間とB - C間という2つのアクティブな接続が存在しています。Bがこの両方の接続を制御している場合にtpreturn()の呼出しを行うと、呼出しは失敗し、すべてのオープン接続にTPEV_SVCERR
イベントが通知され、接続が切断されます。
TPRECVONLY
フラグを設定してtpsend()を呼び出し、B - C間の接続の制御をCに渡します。 TPSUCCESS
、TPFAIL
、またはTPEXIT
を設定して、tpreturn()を呼び出します。TPEV_SVCSUCC
またはTPEV_SVCFAIL
)を通知します。注: | 会話型サービスは、別のサービスと通信するためにリクエスト/レスポンス型の呼出しを行うことができます。そのため、前述の例では、BからCへの呼出しにtpconnect()ではなくtpcall()またはtpacall()を使用することもできます。ただし、会話型サービスがtpforward()を呼び出すことはできません。 |
エラーの発生により切断する唯一の方法は、tpdiscon(3c)関数を呼び出すことです(「プラグを抜くこと」と同じです)。この関数を呼び出すことができるのは、会話のイニシエータ(クライアント)のみです。
注: | この方法で会話を終了することはお薦めしません。アプリケーションを正常に終了するには、サブオーディネート(サーバー)がtpreturn()関数を呼び出す必要があります。 |
tpdiscon()
関数の呼出しには、次のシグネチャを使用します。
int
tpdiscon(intcd
)
cd
引数は、接続が確立したときにtpconnect()関数によって返される接続記述子を指定します。
tpdiscon()
関数は、接続の相手側のサービスに対してTPEV_DISCONIMM
イベントを生成し、cd
を無効にします。トランザクションが実行中の場合、そのトランザクションは中断され、データは失われます。
cd
で接続の開始側と識別されていないサービスからtpdiscon
()が呼び出されると、その呼出しは失敗し、エラー・コードTPEBADDESC
が生成されます。
イベントおよびエラー・コードの全リストとその説明については、『Oracle Tuxedo ATMI C言語関数リファレンス』の「tpdiscon(3c)」を参照してください。
次のコマンドを使用して、会話型のクライアントおよびサーバーをビルドします。
会話型サービスとリクエスト/レスポンス型サービスでは、次の操作を行うことはできません。
Oracle Tuxedoシステムの会話型通信では、5つのイベントが認識されます。これらのイベントはすべてtprecv()に通知でき、そのうちの3つはtpsend()にも通知できます。
表7-3は、イベント、そのイベントを受け取る関数、および各イベントの詳細な説明を示しています。
接続の制御が渡されました。この時点で、このプロセスはtpsend()を呼び出すことができます。
|
||
接続はすでに切断され、通信を継続することはできません。tpdiscon()関数はこのイベントを接続の開始側に通知します。従属サービスとの接続がオープンしたままになっている場合に、tpreturn()が呼び出されたときは、このイベントをすべてのオープン接続に送信します。接続はエラーが原因で切断されます。トランザクションが存在している場合は、中断されます。
|
||
接続の開始側が受信します。通常は、従属プログラムが接続の制御を持たない場合に、tpreturn()を呼び出したことを示します。
|
||
接続の開始側が受信します。従属プログラムが
TPSUCCESS またはTPFAIL 、および妥当なデータ・バッファを使用してtpreturn()を呼び出したが、エラーが発生して呼出しが完了しなかったことを示します。
|
||
接続の開始側が受信します。従属プログラムが接続の制御を持たない場合にtpreturn()を呼び出し、
TPFAIL またはTPEXIT 、およびデータなしでtpreturn() が呼び出されたことを示します。
|
||