クライアント/サーバーのソケット・プログラム: ブロック、非ブロック、および非同期のソケット呼び出し
入出力呼び出しがイベントの完了を待っている場合、ソケットは ブロック・モードになります。 ソケットに対してブロック・モードが設定されていると、呼び出し側プログラム は、求められたイベントが完了するまで中断されます。
FCNTL() または IOCTL() 呼び出しによって非ブロックが設定された場合は、入出力呼び出しが完了していない場合であっても、呼び出し側プログラムは 続行されます。 入出力呼び出しを完了できない場合には、ERRNO EWOULDBLOCK を出して戻ります。 (EWOULDBLOCK を戻したソケット呼び出しの完了をテストする場合、呼び出し側プログラムは SELECT() を使用してください。)
ソケットが利用できるデータがなく、しかも、そのソケットがブロック・モード および非同期モードである場合、READ 呼び出しはデータが届くまでの間、呼び出し側をブロックします。
IBM® TCP/IP サービスのソケット API は、すべて、非ブロック・ソケット呼び出しをサポートします。 API の中には、非ブロック呼び出しのほかに、非同期ソケット呼び出しを サポートするものもあります。
- ブロック
- ソケット呼び出しのデフォルト・モードはブロックです。 ブロックの呼び出しは、ユーザーによって要求されたイベントが完了するまで ユーザーのプログラムに戻りません。 例えば、ブロックの recvfrom() 呼び出しを発行した場合、他の ソケット・アプリケーションからデータを使用できるようになるまで、ユーザーの プログラムには戻りません。 ブロックの accept() 呼び出しは、クライアントがユーザーの ソケット・プログラムに接続するまでユーザーのプログラムには戻りません。
- 非ブロック
-
コマンド FIONBIO と非 0 の 2 進数値を用いたフルワード (4 バイト) 引数 を指定する ioctl() 呼び出しを使用して、ソケットを非ブロッキング・モードに 変更します。 関連するソケット記述子に対する、後続のソケット呼び出しは 非ブロック呼び出しとなります。
代替案としては、F_SETFL コマンド、および引数として FNDELAY を 用いた fcntl() 呼び出しを使用してください。
非ブロック呼び出しは、即時にユーザーのプログラムに戻り、要求されたサービスが 完了したかどうかを示します。エラー番号は、ユーザーの呼び出しがブロック呼び出しであったために その呼び出しがブロックされた可能性があることを意味していることがあります。
例えば、呼び出しが recv() 呼び出しであった場合、ユーザーのプログラムは、 独自の待機論理を設定してあって、後で非ブロックの recv() 呼び出しを再発行 することが可能です。 この手法を使用することで、ユーザーのプログラムは独自のタイムアウト規則を 設定して、アプリケーションが決定した時間内において、パートナー・プログラム からのデータの受信が失敗したソケットをクローズすることが可能になります。
コマンド FIONBIO と 0 という値のフルワード引数 (F'0') を使用して、ソケットを非ブロッキング・モードからブロック・モードに変更する場合は、新しい ioctl() 呼び出しを使用することができます。
- 非同期
- 非ブロッキング呼び出しと同様に、非同期呼び出しは即時にユーザーのプログラムに 制御を戻します。 ただし、非同期呼び出しの場合には、呼び出しを再発行する必要はありません。 非同期呼び出しは、マクロ API で使用することができます。詳しくは、タスク管理および非同期関数の処理を参照してください。
表 1 では、ソケット・プログラミング・インターフェースによって行われる処置 をリストしています。
呼び出しのタイプ | ソケット状態 | ブロック | 非ブロック |
---|---|---|---|
read() 呼び出しのタイプ | 入力データは使用可能 | 即時に戻る | 即時に戻る |
入力データは使用不能 | 入力待ち | EWOULDBLOCK エラー番号を表示して即時に戻る (select() exception: READ) | |
write() 呼び出しのタイプ | 出力バッファーが使用可能 | 即時に戻る | 即時に戻る |
出力バッファーが使用不能 | 出力バッファー待ち | EWOULDBLOCK エラー番号を表示して即時に戻る (select() exception: WRITE) | |
accept() 呼び出し | 新規接続 | 即時に戻る | 即時に戻る |
キューに入れられた接続はない | 新規接続待ち | EWOULDBLOCK エラー番号を表示して即時に戻る (select() exception: READ) | |
connect() 呼び出し | 待機 | EINPROGRESS エラー番号を表示して即時に戻る (select() exception: WRITE) |
select() 呼び出しを使用して、同期プログラムのいくつかのソケットで保留 になっている活動をテストしてください。 活動についてテストしたいソケット記述子のリストを select() 呼び出しに渡し、ソケット記述子によって、以下のテスト検索したい活動のタイプを 指定します。
- 読み取り保留中のデータ
- 新規書き込み作動可能
- 例外条件
select() 呼び出しの論理を使用するとき、そのソケットで何かが起きたこと (例えば、データが届いたこと、および read() 呼び出しによる読み取り準備が 整ったことなど) を select() 呼び出しが通知するまでは、そのソケットで いかなるソケット呼び出しも行わないでください。 select() 呼び出しを使用することで、その呼び出しがブロック不能であることが わかるまで、ブロック呼び出しを出しません。
select() 呼び出し自体は、ブロック、非ブロック、または非同期 (マクロ API の場合) のいずれでも 構いません。呼び出しがブロックで、select() 呼び出しに渡されたリストに入っている ソケット記述子のいずれにも活動がない場合、記述子の 1 つが活動を持つまで、 もしくは、select() 呼び出しに渡されたタイマー値が満了するまで、呼び出しはユーザーのプログラムに戻りません。
select() 呼び出しと selectex() 呼び出しが使用できます。 select() 呼び出しと selectex() 呼び出しの相違点は、selectex() 呼び出しを 使用すると、selectex() 呼び出しを起動して完了することができるイベントの リストに非ソケット関連のイベントを組み込むことができるということです。 これは、selectex() 呼び出しで 1 つまたは複数の MVS™ イベント制御ブロック (ECB) を渡すことで実行されます。選択リストに組み込まれているソケットのいずれかに活動がある場合、指定されたタイマーが満了した場合、もしくは外部イベントのいずれかが完了した 場合、selectex() 呼び出しはユーザーのプログラムに戻ります。
一般的に、サーバー・プログラムは、ソケットの活動かオペレーター・コマンド を待ってシャットダウンします。 selectex() 呼び出しを使用することで、活動をモニターするイベントのリストに シャットダウン ECB を組み込むことができます。