Contents Up Previous Next

プロセス間通信の概要

クラス: wxServer, wxConnection, wxClient wxWidgets にはプロセス間通信やネットワークプログラミングを支援する様々なクラスがあります。この章では DDE 風のプロトコルを使用するひとつのクラス群についてのみ説明しますが、その代わりに他の有用なクラスの一覧を以下に示します:

wxWidgets の DDE 風プロトコルは Windows DDE に基づく高レベルのプロトコルです。このDDE 風プロトコルには 2 種類の実装があります: ひとつは実際の DDE を使用する方法で、WIndows のみで実行できます。もうひとつは TCP/IP (ソケット) を使用する方法で、ほとんどのプラットフォームで実行できます。クラス名を除いて API と仮想的な振る舞いがすべて同じであるため、ふたつの実装を簡単に切り替えられることに気がつくと思います。

<wx/ipc.h> をインクルードすることで IPC クラス用の便利なシノニムを定義できます: DDE ベースの実装とソケットベースの実装のどちらを使用するかによって wxDDEServer もしくは wxTCPServer のいずれかが wxServer として定義されます。同様のことが wxClientwxConnection に対しても行われます。

Windows ではデフォルトで DDE 版が使用されます。DDE は同じコンピュータ内でのみ動作します。もし異なるワークステーション間で IPC を使用したい場合、このヘッダファイルをインクルードする前に wxUSE_DDE_FOR_IPC を 0 に定義してください。これにより、Windows でも強制的に TCP/IP 版が使用されるようになります。

以降の説明では wx... という名称を使用しますが、同じ wxTCP... クラスと wxDDE... クラスは同様の方法で使用できることを覚えておいてください。

DDE 風 API では中心となるクラスが 3 種類あります:

  1. wxClient. これはクライアントアプリケーションを表しており、クライアントプログラムの中でだけ使用できます。
  2. wxServer. これはサーバアプリケーションを表しており、サーバプログラムの中でだけ使用できます。
  3. wxConnection. これはクライアントからサーバへのコネクションを表しています。クライアントとサーバの両方とも、このクラスのインスタンスをコネクションごとにひとつ使用します。ほとんどの DDE トランザクションはこのオブジェクト上で行われます。

通常、アプリケーション間のメッセージは 3 種類の変数で識別されます: コネクションオブジェクト、トピック名、アイテム名です。いくつかのメッセージではデータ文字列が 4 番目の要素になります。コネクション (Windows で言うところの会話 (conversation)) を作成するにはクライアントアプリケーションでサービス名 (サーバを識別します) とトピック名 (接続している間のトピックを識別します) を指定して wxClient::MakeConnection を呼び出します。Unix におけるサービス名はインターネットドメインソケットが通信に使用する整数のポート識別子か、Unix ドメインソケットが作成する有効なファイル名 (このファイルは存在してはならず、後で削除されます) のいずれかになります。

セキュリティ上の注意: インターネットドメインソケットを使用したプロセス間通信は非常に危険です。なぜなら、これらの通信に対するアクセス制御はまったく行われないためです。可能な限り、Unix ドメインソケットを使用してください。

そして、サーバが応答し、接続を拒否または許可します。接続が許可されるとサーバとクライアントの双方で wxConnection が作成され、接続が閉じられるまで維持されます。作成されたコネクションオブジェクトはクライアント・サーバ間でのメッセージの送受信に使用されます。このとき、wxConnection を継承したクラスで仮想関数をオーバーライドすると DDE メッセージを処理することができます。

動作するサーバを作成するには次のようにする必要があります:

  1. wxConnection を継承し、wxConnection のサーバ側へ送信されたメッセージ用のハンドラ (OnExecute、OnRequest、OnPoke など) を用意する。このとき、実際にアプリケーションで必要となるハンドラだけをオーバーライドする必要があります。
  2. wxServer を継承し、トピック引数に基づいて接続を許可または拒否するために OnAcceptConnection をオーバーライドする。接続を許可する場合、継承したコネクションクラスのインスタンスをこのメンバ関数で作成し、返却する必要があります。
  3. サーバオブジェクトのインスタンスを作成し、作成したオブジェクトを有効化するためにサービス名を指定して Create を呼び出す。

動作するクライアントを作成するには次のようにする必要があります:

  1. wxConnection を継承し、wxConnection のクライアント側へ送信されたメッセージ用のハンドラ (OnAdvise など) を用意する。このとき、実際にアプリケーションで必要となるハンドラだけをオーバーライドする必要があります。
  2. wxClient を継承して OnMakeConnection をオーバーライドし、継承したコネクションクラスのインスタンスを作成して返却する。
  3. クライアントオブジェクトのインスタンスを作成する。
  4. 適切なときにホスト名 (Unix の場合のみ使用されます。ローカルコンピュータを指定する場合は 'localhost' を使用してください)、サービス名、この接続用のトピック名を指定して wxClient::MakeConnection を呼び出し、新しいコネクションを作成する。接続に成功するとクライアントオブジェクトは継承したコネクションクラスのオブジェクトを作成するために OnMakeConnection を呼び出します。
  5. サーバへメッセージを送信するには wxConnection のメンバ関数を使用してください。

データの転送

DDE の詳細


データの転送

他のアプリケーションへデータを転送するにはいくつかの方法があります。これらは wxConnection の関数です。

デフォルトのデータ型は wxCF_TEXT (ASCII テキスト) で、デフォルトのデータサイズはヌル終端文字列の文字列長です。また、Windows 独自のデータ型を使用することもできます。


IPC サンプルディレクトリにある serverclient のサンプルプログラムを参照してください。サーバを実行し、それからクライアントを実行してください。このサンプルでは Advise ループとともに Execute、Request、Poke コマンドを使用しています: サーバ側のリストボックスを選択すると、選択された項目がクライアント側のリストボックスでハイライトされます。


DDE の詳細

wxClient オブジェクトは DDE 風 (Dynamic Data Exchange) 通信のクライアント・サーバ通信のクライアント部分を初期化します。(Windows と Unix の両方で利用可能です)

適切なサーバと通信するクライアントを作成するには wxConnection と wxClient をそれぞれ継承する必要があります。wxConnection の継承クラスはサーバとの '会話' (conversation) におけるやり取りを受信します。そして wxServer を継承したクラスが必要になります。これにより、接続が確立したときに wxClient::OnMakeConnection をオーバーライドした関数が要求されたクラスの wxConnection を返却できるようになります。

以下に例を示します:

class MyConnection: public wxConnection {
 public:
  MyConnection(void)::wxConnection() {}
  ~MyConnection(void) { }
  bool OnAdvise(const wxString& topic, const wxString& item, char *data, int size, wxIPCFormat format)
  { wxMessageBox(topic, data); }
};

class MyClient: public wxClient {
 public:
  MyClient(void) {}
  wxConnectionBase *OnMakeConnection(void) { return new MyConnection; }
};

ここでは MyConnection がサーバから送信された OnAdvise メッセージに反応してメッセージボックスを表示します。

クライアントアプリケーションを実行するときには wxClient の継承クラスのインスタンスを作成する必要があります。以下ではコマンドライン引数を使用してホスト名 (サーバを実行しているマシン名)、(サーバプロセスを識別する) サーバ名を引き渡しています。wxClient::MakeConnection を呼び出すと接続要求が受け付けられた場合に MyConnection のインスタンスが暗黙的に作成されます。そして、クライアントはサーバからの Advise ループを要求します。(Advise ループとはデータが変更されたときにサーバがクライアントを呼び出すところのことです)

  wxString server = "4242";
  wxString hostName;
  wxGetHostName(hostName);

  // 新しいクライアントを作成する
  MyClient *client = new MyClient;
  connection = (MyConnection *)client->MakeConnection(hostName, server, "IPC TEST");

  if (!connection)
  {
    wxMessageBox("Failed to make connection to server", "Client Demo Error");
    return NULL;
  }
  connection->StartAdvise("Item");