第11章  RPGでソケット通信しよう!
RPGプログラマーの為のC言語講座

ソケット通信はTCPIPの通信プログラムのインターフェースですが、AS/400では V310より、Cソケットをサポートしています。それ以前は、Pascalでソケット通信 をサポートしていました。

RPGでは、ILE/OPMともに残念ながらサポートしていません。
今後のサポートもおそらくはないでしょう。

だからといって、RPGでソケット通信を行うのをあきらめる必要はありません。

ソケット関数ごとにPGMを作成し、RPGからCALLするようにすれば、RPGでも (というよりは言語をとあず)ソケット通信が可能になります。

実際、SNAのCPI−Cでは、CALL形式でRPGでのAPPC通信をサポート しています。

これと同じ仕組みを使ってTCPIPでも、CALL形式でソケット通信を実装すればよいのです。

以下実際のプログラムを通してその方法について解説します。

まず、RPGから呼び出して利用するCのプログラム開発の基本的な指針を以下のように定義します。

  1. RPG<−>C間のパラメーター渡しは、最少限度に絞る。
    呼び出しのオーバーヘッドを最少にするのと、コーディングをシンプルにする目的のため
    ソケット関数の呼び出しパラメータには、可能なかぎり固定値を設定する。

  2. 呼び出されるプログラムは、単機能のPGMとし、呼び出す実際のソケット関数が複数機能をもつ場合は、 別プログラムとして実装する。
    基本的には、ソケット関数とCプログラムは1対1に対応して実装するが、もし、利用するソケット関数が 複数機能をもちパラメーターで指示するタイプの物である場合は、用途に合わせて、別プログラムとして実装する。
    これは、パラメーターの設定ミスを避けるのと、呼び出しを単純化する目的である。

  3. RPG<−>C間のパラメータの型は、特別な場合を除き、char(文字型)とする。
    型の違いによるコンバージョン作業を省略するため、RPG側のインターフェースは、常に文字型とし、必要な 型変換は、呼びたされるCのプログラム内で処理するものとする。

  4. 戻り値は、使用できないので、戻り値に相当する引数を用意する。
    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プログラムにより、ソケットのクローズを行います。

上記の7.8.はLOOPするものとします。