ソケット通信はTCPIPの通信プログラムのインターフェースですが、AS/400では
V310より、Cソケットをサポートしています。それ以前は、Pascalでソケット通信
をサポートしていました。
RPGでは、ILE/OPMともに残念ながらサポートしていません。
今後のサポートもおそらくはないでしょう。
だからといって、RPGでソケット通信を行うのをあきらめる必要はありません。
ソケット関数ごとにPGMを作成し、RPGからCALLするようにすれば、RPGでも
(というよりは言語をとあず)ソケット通信が可能になります。
実際、SNAのCPI−Cでは、CALL形式でRPGでのAPPC通信をサポート
しています。
これと同じ仕組みを使ってTCPIPでも、CALL形式でソケット通信を実装すればよいのです。
以下実際のプログラムを通してその方法について解説します。
まず、RPGから呼び出して利用するCのプログラム開発の基本的な指針を以下のように定義します。
- RPG<−>C間のパラメーター渡しは、最少限度に絞る。
呼び出しのオーバーヘッドを最少にするのと、コーディングをシンプルにする目的のため
ソケット関数の呼び出しパラメータには、可能なかぎり固定値を設定する。
- 呼び出されるプログラムは、単機能のPGMとし、呼び出す実際のソケット関数が複数機能をもつ場合は、
別プログラムとして実装する。
基本的には、ソケット関数とCプログラムは1対1に対応して実装するが、もし、利用するソケット関数が
複数機能をもちパラメーターで指示するタイプの物である場合は、用途に合わせて、別プログラムとして実装する。
これは、パラメーターの設定ミスを避けるのと、呼び出しを単純化する目的である。
- RPG<−>C間のパラメータの型は、特別な場合を除き、char(文字型)とする。
型の違いによるコンバージョン作業を省略するため、RPG側のインターフェースは、常に文字型とし、必要な
型変換は、呼びたされるCのプログラム内で処理するものとする。
- 戻り値は、使用できないので、戻り値に相当する引数を用意する。
RPGのCALLは、戻り値を受け取ることができないので、必要な場合は、それに相当するパラメーターを用意する
このような方針で、まずソケット通信に最低限必要な下記のソケット関数について、Cのプログラムを用意しましょう
ソケット関数 | Cのプログラム名 | 説 明 |
socket() | SKOPEN | ソケットの作成 |
bind() | SKBIND | ソケットのバインド |
listen() | SKLISN | ソケットのリッスン |
accept() | SKACPT | ソケットのアクセプト |
connect() | SKCONN | ソケットのコネクト |
close() | SKCLOS | ソケットのクローズ |
send() | SKSEND | データの送信 |
read() | SKRECV | データの受信 |
gethostbyname() | SKGETH | ホスト名からIP検索 |
上記のPGMはSocket RPGとして、一つのパッケージにまとめました。
それでは実際に、これらのプログラムを利用して、
RPGによるソケット通信のプログラムを作成してみましょう
作成するサンプルのRPGは、以下の様なプログラムとします。
サーバーRPG |
クライアントRPG |
1.ソケットのオープン
SKOPENプログラムによりソケットをオープンします。SKOPENでは、setsocketオプションで、
TCP_NODELAY,SO_REUSEADDRをセットしています。
|
1.ソケットのオープン
SKOPENプログラムによりソケットをオープンします。SKOPENでは、setsocketオプションで、
TCP_NODELAY,SO_REUSEADDRをセットしています。
|
2.バインド
SKBINDプログラムによりソケットにIPアドレス/ポート番号を割り当てます。
SKBINDでは、明示的なIP割り当ての代わりにANYとしてどのインターフェースからの
接続要求についても受けとれります。
|
なし |
3.リッスン
SKLISNプログラムにより、クライアントからの接続要求を待ちます。
|
なし |
なし |
4.コネクト
SKCONNプログラムにより、サーバーに接続を行います。IPアドレスは、
構内ループバックアドレス(127.0.0.1)を指定しているので、サーバーと同じマシン上で
クライアントも実行すると仮定しています。
|
5.アクセプト
SKACPTプログラムにより、クライアントからの接続要求を受け入れます。
この際に、新しいソケットディスクリプターがシステムにより与えられます。これ以降の通信は
ここで割り当てられた新しいディスクリプターを使用します。
|
なし |
6.クローズ
SKCLOSプログラムにより、最初に作成したlisten用のソケットディスクリプターをクローズします。
通常のtcpipサーバーは、接続要求を受けたあとの処理は、子プロセスを作成し、個別の通信はその子プロセスに
ませるようにするのが一般的です。
しかし、RPGでは、子プロセスやスレッド処理をサポートしないため、ここでは、別のプログラムが新たに
そのポートでlisten出来るように、ソケットをクローズしています。
|
なし |
7.データ受信
SKRECVプログラムにより、クライアントから送信された文字列を受信し、画面表示します。
|
7.データ送信
SKSENDプログラムにより、画面から入力された文字列を送信します。
|
8.データ送信
SKSENDプログラムにより、7.でクライアントから受信した文字列をそのまま送信します。
(エコー処理)
|
8.データ受信
SKRECVプログラムにより、サーバーから送信された文字列を受信し、画面表示します。
(エコー処理)
|
9.ソケットクローズ
文字列[EXIT]が送られてきた場合は、SKCLOSプログラムにより、ソケットのクローズを行います。
|
9.ソケットクローズ
画面からF3が押されるか、サーバープログラムが終了した場合は、SKCLOSプログラムにより、ソケットのクローズを行います。
|