会話型通信はOracle Tuxedoシステムのメッセージ交換のパラダイムで、人の会話に似た通信がATMIクライアントおよびサーバー間で実装されています。この通信方法では、クライアント(イニシエータ)とサーバー(サブオーディネート)間で仮想接続が行われて、双方で会話の状態に関する情報が保持されます。この接続は、接続を終了するイベントが発生するまで継続します。
会話型通信では、クライアントとサーバー間に
半二重接続が確立されます。半二重接続では、メッセージが1方向だけに送信されます。接続に関する制御は、イニシエータからサブオーディネートへ、またはその逆に移ります。制御を持つプロセスがメッセージを送信でき、持たないプロセスは受信しかできません。
図7-1の銀行業務のオンライン・アプリケーションを例に、Oracle Tuxedo ATMIアプリケーションで行われる会話型通信について説明します。この例では、銀行の顧客が過去2か月間の当座預金の明細書をリクエストしています。
1.
|
顧客が過去2か月間の当座預金口座の明細書をリクエストします。
|
2.
|
口座レコード管理システムは、当座預金口座の最初の月の明細書を送信し、次に、次の月の明細書を送信するかどうかを Moreプロンプトで確認して応答します。
|
3.
|
顧客は Moreプロンプトを選択して、次の月の明細書をリクエストします。
|
注意:
|
口座レコード管理システムでは、状態情報を保持して、顧客が Moreプロンプトを選択した場合にどの明細書を送るのか認識できるようにする必要があります。
|
4.
|
口座レコード管理システムは、次の月の明細書を送信します。
|
リクエスト/レスポンス型通信の場合と同じように、Oracle Tuxedoシステムでは型付きバッファを使用してデータが渡されます。アプリケーションがバッファ・タイプを認識できることが必要です。バッファ・タイプの詳細は、
2-2ページの「型付きバッファの概要」を参照してください。
会話型のクライアントおよびサーバーには、次の特徴があります。
•
|
会話型のクライアントとサーバー間の論理接続は、接続が終了するまで継続します。
|
•
|
会話型のクライアントとサーバー間の接続で転送できるメッセージの数には制限はありません。
|
•
|
クライアントとサーバーとの会話では、データの送受信に tpsend()および tprecv()ルーチンが使用されます。
|
会話型通信は、次の点でリクエスト/レスポンス型通信と異なります。
•
|
会話型クライアントは、会話型サーバーにサービス・リクエストを送信します。
|
•
|
会話型サービスを定義するために、構成ファイルに会話型サーバーの一部が予約されています。
|
tpconnect()関数の呼出しには、次のシグネチャを使用します。
int
tpconnect(char *
name, char *
data, long
len, long
flags)
表7-1は、
tpconnect()関数の引数を示しています。
|
|
|
会話型サービス名を指す文字型のポインタ。 nameに会話型サービスを指すポインタが指定されていない場合、呼出しが失敗して -1が返され、 tperrnoにエラー・コード TPENOENTが設定されます。
|
|
データ・バッファを指すポインタ。 data引数に、 tpalloc()を使用してすでに割り当てられているバッファを指すポインタを設定すると、接続の確立と同時にデータを送信することができます。バッファのタイプ とサブタイプ は、呼び出されたサービスで認識できなければなりません。 dataにNULLを設定して、送信データがないことを示すことができます。
呼び出された会話型サービスは、 TPSVCINFOデータ構造体を介して dataおよび lenポインタを受け取ります。この構造体は、サービスが呼び出されたときに main()関数によって渡されます。(リクエスト/レスポンス・サービスも同じ方法で、 dataおよび lenポインタを受け取ります。) TPSVCINFOデータ構造体の詳細は、 5-9ページの「サービスの定義」を参照してください。
|
|
データ・バッファの長さ。バッファが自己記述型( FMLバッファなど)の場合、 lenに0を設定できます。
|
|
フラグの設定値。有効なフラグの設定値については 『Oracle Tuxedo ATMI C言語関数リファレンス』の 「tpconnect(3c)」を参照してください。
システムは、 TPSVCINFO構造体のフラグ・メンバーを使用して呼び出されたサービスに通知します。
|
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データ構造体の詳細は、 5-9ページの「サービスの定義」を参照してください。
|
|
データ・バッファの長さ。バッファが自己記述型( FMLバッファなど)の場合、 lenに0を設定できます。 dataに値が設定されていない場合、この引数は無視されます。
|
|
エラーの発生時(つまり、 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(int
cd, char **
data, long *
len, long
flags, long *
revent)
次の表は、
tprecv()関数の引数を示しています。
|
|
|
接続記述子。従属プログラムで呼出しを行う場合は、 cd引数に、そのプログラムの TPSVCINFO構造体に指定されている値を設定します。発信元のプログラムで呼出しを行う場合は、 cd引数に、 tpconnect()関数で返される値を設定します。
|
|
データ・バッファを指すポインタ。 data引数は、 tpalloc()を使用してすでに割り当てられているバッファを指す必要があります。バッファのタイプ とサブタイプ は、呼び出されたサービスで認識できなければなりません。NULLを指定すると呼出しは失敗し、 tperrno(5)に TPEINVALが設定されます。
呼び出された会話型サービスは、TPSVCINFOデータ構造体を介してdataおよび lenポインタを受け取ります。この構造体は、サービスが呼び出されたときに main()関数によって渡されます。(リクエスト/レスポンス・サービスも同じ方法で、 dataおよび lenポインタを受け取ります。) TPSVCINFOデータ構造体の詳細は、 5-9ページの「サービスの定義」を参照してください。
|
|
データ・バッファの長さ。バッファが自己記述型(FMLバッファなど)の場合、 lenに0を設定できます。NULLを指定すると呼出しは失敗し、 tperrno(5)に TPEINVALが設定されます。
|
|
エラーの発生時(つまり、 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()の呼出しが成功した場合
|
次の項では、会話を正常に終了する方法について、2つの例を挙げて説明します。これらの会話には、
tpreturn()関数を使用するグローバル・トランザクションは含まれていません。
最初の例では、2つのコンポーネント間の単純な会話を終了する方法を示します。2番目の例では、会話が階層構造になっている複雑な会話を終了する方法を示します。
接続がオープンになっているときに会話を終了すると、エラーが返されます。その場合、
tpcommit()または
tpreturn()は失敗します。
図7-2は、正常に終了するAとB間の単純な会話を示しています。
1.
|
Aは、 TPSENDONLYフラグで tpconnect()を呼び出して接続を設定します。このフラグは、Bが会話の受信側であることを示します。
|
2.
|
Aは TPRECVONLYフラグで tpsend()を呼び出して、接続の制御をBに移します。その結果、 TPEV_SENDONLYイベントが生成されます。
|
3.
|
Bが次に tprecv()を呼び出すと-1が返され、 tperrno(5)に TPEEVENTが設定されてます。 revent引数に TPEV_SENDONLYが返されて、制御がBに移ったことが示されます。
|
4.
|
Bは、 rvalに TPSUCCESSを設定して tpreturn()を呼び出します。この呼出しにより、Aに対して TPEV_SVCSUCCイベントが生成され、接続が正常に切断されます。
|
5.
|
Aは、 tprecv()を呼び出して、イベントが発生したことと会話が終了したことを認識します。イベント TPEV_SVCFAILが発生した場合でも、この tprecv()への呼出しでデータを受信できます。
|
注意:
|
この例では、Aはクライアントまたはサーバーのどちらでもかまいませんが、Bはサーバーでなければなりません。
|
図7-3は、正常に終了する階層構造の会話を示しています。
この例では、サービスBは会話のメンバーで、2番目のサービスCとの接続を開始しています。つまり、A - B間とB - C間という2つのアクティブな接続が存在しています。Bがこの両方の接続を制御している場合に
tpreturn()の呼出しを行うと、呼出しは失敗し、すべてのオープン接続に
TPEV_SVCERRイベントが通知され、接続が切断されます。
両方の接続を正常に終了するには、次の処理を順に行います。
1.
|
Bは、Cとの接続に TPRECVONLYフラグを設定して tpsend()を呼び出し、B - C間の接続の制御をCに渡します。
|
2.
|
Cは、状況に応じて rvalに TPSUCCESS、 TPFAIL、または TPEXITを設定して、 tpreturn()を呼び出します。
|
3.
|
Bは、 tpreturn()を呼び出し、Aにイベント( TPEV_SVCSUCCまたは TPEV_SVCFAIL)を通知します。
|
エラーの発生により切断する唯一の方法は、
tpdiscon(3c)関数を呼び出すことです(「プラグを抜くこと」と同じです)。この関数を呼び出すことができるのは、会話のイニシエータ(クライアント)のみです。
注意:
|
この方法で会話を終了することはお薦めしません。アプリケーションを正常に終了するには、サブオーディネート(サーバー)が tpreturn()関数を呼び出す必要があります。
|
tpdiscon()関数の呼出しには、次のシグネチャを使用します。
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()が呼び出されたことを示します。
|
|
接続の開始側が受信します。従属サービスの処理が正常に終了しなかったこと(つまり、 tpreturn()が TPFAILまたは TPEXITで呼び出されたこと)を示します。
|
|
|
接続の開始側が受信します。従属サービスの処理が正常に終了したこと(つまり、 tpreturn()が TPSUCCESSで呼び出されたこと)を示します。
|