簡単な自己紹介と背景
データベースソフト 4th Dimension (以下4D)を使って歯科用の電子カルテ(カルテメーカー)を開発しています。開発開始は1993年、4D v1の時代に遡ります。製品としてリリースしたのは4Dv3.1でクライアント/サーバー形態になってからの1994年です。以来30年、地道にアップデートを重ね、現在はv19ベースでリリースしています。
カルテメーカーは2000年ごろから、堅牢性や無停止性の向上を目指して、クライアント/サーバーの形態から、スタンドアロンをネットワークで繋げてP2Pでデータを共有するハイブリッドP2Pの形態に変化しました。
このP2Pを支えているのが、4Dの標準プラグインの 4D InternetCommands (以下4D IC)です。このプラグインの中の 低レベルTCP/IP通信機能 のコマンドを使ってピア間の通信を実装していました。
2024年4月に、この4D ICの機能の多くが標準コマンドに置き換わったことを理由にプラグインの廃止がアナウンスされました。確かにほとんどの機能はすでに取り込まれていたのですが、肝心の低レベル通信機能はまだ標準コマンドにはなく、なんと、以後も低レベル通信機能は実装されないことが正式に発表されてしまいました😭
廃止はv21からになりそうなので、緊急に対応しないといけないという状況ではないのですが、いずれやらなくてないけないことは確定です。
そんなわけで、いろいろ試行錯誤をはじめたわけですが、この記事はその対応のための備忘録とし書きはじめたものです。
4D InternetCommandsとは
初期の頃の4Dにはインターネット関係の標準コマンドは存在していませんでした。メールの送受信等を行うには外部機能が必要で、それを4D社がプラグインの形で供給していました。このプラグインには、
- IMAPメール
- POP3メール
- TCP/IP
- UDP
- FTP
- SMTP
- ユーティリティ
などのプロトコルを扱うコマンドが実装されていました。
今回、自力で実装しなくてはいけなくなったのは、この中のTCP/IP機能です。
これには、
- TCP_Close
- TCP_Listen
- TCP_Open
- TCP_Receive
- TCP_ReceiveBLOB
- TCP_Send
- TCP_SendBLOB
- TCP_State
というコマンドが含まれています。コマンド名から推測できるかと思いますが、ソケットによるTCP/IP通信を実装した感じのものです。
サーバー側ではTCP_Listenでポートを受信状態にし、クライアント側ではTCP_Openでサーバーに接続、TCP_Receive、TCP_Send等でデータを通信、TCP_Closeで接続を切ります。
扱いも簡単で、4Dのプロセスによるマルチスレッド機能と組み合わせるととても柔軟な通信環境を簡単に構築できます。
特に初期の頃、実際に通信を行うOSの実装は、MacTCP→Open Transportと変遷し、途中からWindows対応となったためWinSockが追加され、MacもOS XになってBSD Socketsに変更になったのですが、その間OSの変化をまったく意識しないでプログラムの変更もなく対応できたのは、この4D ICプラグインがあったからこそでした。
とにかく情報収集
こんな便利なプラグインだったので、まさかなくなるとは思っていませんでした。便利すぎて逆にプラグインの中身なんて全く意識していませんでしたので、ソケットによる通信機能のプログラミングの知識がまったくありません。
こんな時はGoogleさんと、今時はChatGPTさん
とは言っても、やはりどうしても断片的な情報になってしまい、理解できたかという微妙。
ということで
こちらの記事の最後で紹介されていた、こちらの本を入手。
基礎からわかるTCP/IPネットワ-ク実験プログラミング: Linux/FreeBSD対応
基本的なソケットの使い方を学べる良書でした。
書いてみよう
なんとなく理屈はわかったけど、プログラムは書いてナンボ。
というわけでとにかく書いてみることにしました。
とは言っても、実のところ4DのプラグインというかC言語での開発はHyperCard時代のXCMD、XFCN、4Dのごく初期の頃のプラグイン開発以来。
使ってた環境はTHINK-CとかCodeWarriorとか。
OS XになってFreeBSDベースの本格的な開発の経験はありません。
Xcode自体はiOSでのアプリケーション開発経験があるので、ある程度理解しているのですが、とりあえず書くならコマンドラインベースのテストプログラム。
う〜む、どうやるんだろ(^^;
コマンドラインって、バリバリ使ってたのはz80自作マイコン時代のCP/M
UNIXの作法はいまいちわかってない
ちょっと調べると gcc とかでコンパイルとか...
まぁ、Xcode使った方が簡単かもという直感を信じてXcodeを開いて、新規プロジェクト。
Command Line Toolというアイコンがあったので、これを選択
保存場所を聞いてくるので、保存すると
こんなソースのプロジェクトが開きます。
左上の「▶︎」アイコンを押すとコンパイル、ビルドが行われ実行されます。
結果、右下のスクリーンに
Hello, World!
Program ended with exit code: 0
と表示されコードが正しく実行されていることが確認できます。
ちなみに
Productメニュー → Show Build Forder in Finder
と選択するとファインダが開いてBuildフォルダがハイライトされるので、Build → Products → Debugとして開くと「ts」という実行ファイルが見つかります。
ターミナルアプリケーションを開いて、cdでカレントディレクトリを上記のDebugにして「./ts」とするとちゃんとコマンドラインツールとして実行されます。
MacBookPro2023 Debug % ./ts
Hello, World!
おぉ、ちょっと感動
ターミナルが開いているので、試しにコマンドラインからコンパイル&ビルドしてみましょう。
カレントディレクトリをプロジェクトを保存したフォルダからmain.cソースファイルを含むディレクトリにして
MacBookPro2023 ts % gcc main.c
とすると、実行ファイル「a.out」が同じディレクトリに生成されるので、同じように「./a.out」とするとこれも正しく実行されます。
MacBookPro2023 ts % ./a.out
Hello, World!
では、Xcodeに戻って。
行番号のところをクリックするとブレークポイントが設定できます。
この状態でビルド&実行をすると
と、こんな感じでブレークポイントで止まりデバッガが表示されます。
便利〜
以上、プログラムの開発&テストの目処がたったので、今日はこれでお終い❗️