非ブロッキング入出力を使用するには、clnt_control() 関数の CLSET_IO_MODE rpciomode_t* オプションで RPC_CL_NONBLOCKING 引数を指定して、クライアントハンドルを構成します。詳細は、clnt_control(3NSL) のマニュアルページを参照してください。
トランスポートのキューが満杯の場合には、バッファーが使用されます。次の 2 つの基準が満たされるまで、バッファーが使用され続けます。
バッファーが空になる。
キューが要求をすぐに受け入れられる。
その後、トランスポートのキューが満杯になるまで、要求は直接トランスポートのキューに送られます。バッファーのデフォルトのサイズは、16 K バイトです。
バッファーは自動的に空にされるのではないことに留意してください。バッファーにデータが含まれる場合には、ユーザーがバッファーをフラッシュする必要があります。
CLSET_IO_MODE で RPC_CL_NONBLOCKING 引数を選択している場合は、フラッシュモードを選択することができます。CLSET_FLUSH_MODE に RPC_CLBESTEFFORT_FLUSH または RPC_CL_BLOCKING_FLUSH 引数のいずれかを指定できます。また、clnt_call() などの同期コールを送信することにより、バッファーを空にすることもできます。詳細は、clnt_control(3NSL) のマニュアルページを参照してください。
バッファーが満杯の場合は、RPC_CANTSTORE エラーがクライアントに返され、その要求は送られません。クライアントは、後でそのメッセージを再送信する必要があります。CLGET_CONNMAXREC および CLSET_CONNMAXREC コマンドを使用することにより、バッファーのサイズを確認したり、変更したりすることができます。バッファー内に格納されている、すべての保留状態の要求のサイズを確認する場合は、CLGET_CURRENT_REC_SIZE コマンドを使用します。これらのコマンドについての詳細は、clnt_control(3NSL) のマニュアルページを参照してください。
サーバーは、要求が受け付けられたかどうかや処理されたかどうかの確認は行いません。ユーザーは、要求がバッファーに入った後で clnt_control() を使用すると、要求のステータス情報を入手することができます。
次に例を示す client.c ファイルは、非ブロッキング入出力モードの使用法を例示するために、変更されています。この新しい client_nonblo.c ファイルでは、RPC_CL_NONBLOCKING 引数の使用により入出力モードが非ブロッキングに指定されており、RPC_CL_BLOCKING_FLUSH の使用によりフラッシュモードがブロッキングに選択されています。入出力モードおよびフラッシュモードは、CLSET_IO_MODE で呼び出されます。エラーが発生すると、RPC_CANT_STORE がクライアントに返され、プログラムによりバッファーのフラッシュが試みられます。フラッシュの別のメソッドを選択するには、clnt_control(3NSL) のマニュアルページを参照してください。
#include <stdio.h>
#include "counter.h"
main(int argc, char *argv[])
{
CLIENT* clnt;
enum clnt_stat result;
char *server;
int number;
bool_t bres;
/*
* 使用する入出力モードとフラッシュメソッドを選択する。
* この例では、非ブロッキング入出力モードと
* ブロッキングフラッシュが選択されている。
*/
int mode = RPC_CL_NONBLOCKING;
int flushMode = RPC_CL_BLOCKING_FLUSH;
if (argc != 3) {
fprintf(stderr, "usage: %s server_name number\n", argv[0]);
exit(1);
}
server = argv[1];
number = atoi(argv[2]);
clnt= clnt_create(server, COUNTERPROG, COUNTERVERS, "tcp");
if (clnt == (CLIENT*) NULL) {
clnt_pcreateerror(server);
exit(1);
}
/*
* clnt_control を使用して入出力モードを設定する。
* この例では、非ブロッキング入出力モードが
* 選択されている。
*/
bres = clnt_control(clnt, CLSET_IO_MODE, (char*)&mode);
if (bres)
/*
* フラッシュモードをブロッキングに設定する
*/
bres = clnt_control(clnt, CLSET_FLUSH_MODE, (char*)&flushMode);
if (!bres) {
clnt_perror(clnt, "clnt_control");
exit(1);
}
/*
* RPC サービスを呼び出す。
*/
result = add_1(number, clnt);
switch (result) {
case RPC_SUCCESS:
fprintf(stdout,"Success\n");
break;
/*
* RPC_CANTSTORE は、バッファーが要求を格納できない場合に、
* クライアントに返される新しい値。
*/
case RPC_CANTSTORE:
fprintf(stdout,"RPC_CANTSTORE error. Flushing ... \n");
/*
* バッファーは、ブロッキングフラッシュを使用してフラッシュされる
*/
bres = clnt_control(clnt, CLFLUSH, NULL);
if (!bres) {
clnt_perror(clnt, "clnt_control");
}
break;
default:
clnt_perror(clnt, "call failed");
break;
}
/* フラッシュする */
bres = clnt_control(clnt, CLFLUSH, NULL);
if (!bres) {
clnt_perror(clnt, "clnt_control");
}
clnt_destroy(clnt);
exit(0);
}