.NETリモーティングでIPCチャネルを使用する

.NET2.0から.NETリモーティングで使用できるチャネルに新しくIPCチャネルが追加された。
これは同じマシン間での通信、純粋なプロセス間通信用のチャネルで内部実装には名前付きパイプが使われている。(メモリマップドファイルやったかな?どっちかは忘れた)で、ちょうど同じマシン間でプロセス間通信をする必要があったので使ってみることにした。

まずアプリケーション構成ファイルにチャネルを定義する。

App.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <system.runtime.remoting>
        <application>
            <channels>
                <channel ref="ipc">
                </channel>
            </channels>
        </application>
        <customErrors mode="Off" />
    </system.runtime.remoting>
</configuration>

で、これを公開する。

Program.cs
static void Main() {
    RemotingConfiguration.Configure("Remoting.config", false);

    HogeService hogeService = new HogeService();
    // SAOで公開
    RemotingServices.Marshal(hogeService, "hogeService.rem");
}

このサービスにアクセスするコード

Client.cs

static void Main() {
    HogeService hogeService = (HogeService)Activator.GetObject("ipc://localhost/hogeService.rem");

    hogeService.Do();
}

これで実行してみると、なんか例外が出た。

System.Runtime.Remoting.RemotingException: IPC ポートに接続できません。指定されたファイルが見つかりません。

「指定されたファイルが見つかりません」?なんのこっちゃ?としばらく考えてみて気づいたが、IPCチャネルは名前付きパイプを使っている。なら、そのパイプ名はどこで指定するんや?という話。

MSDNをよく見てみるとアプリケーション構成ファイルでIPCチャネルを指定する場合の必須属性があった。

App.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <system.runtime.remoting>
        <application>
            <channels>
                <channel ref="ipc" portName="hogehoge">
                </channel>
            </channels>
        </application>
        <customErrors mode="Off" />
    </system.runtime.remoting>
</configuration>

「portName」属性でパイプ名を指定できるようになっている。

クライアント側のコードを書き直す。

Client.cs

static void Main() {
    HogeService hogeService = (HogeService)Activator.GetObject("ipc://hogehoge/hogeService.rem");

    hogeService.Do();
}

考えてみれば、同じマシン間でのプロセス間通信を想定したIPCチャネルでホスト名に「localhost」と指定する事にはまったく意味がない。だからその部分でパイプ名を指定するわけだ。( ´_ゝ`)フーン

これで正常に動いた。