Cでの単純なプロセス間通信#

画像

開発者としての後輩の仕事を始めたとき、プロセス間通信のような、当時私には不明瞭だった概念に対処しなければなりませんでした。 それは、1つのアプリケーションのロジックの枠組みの中で、非常に困難な方向を向いた初心者プログラマにとっては完全な野avでした。 プロジェクトはDelphiで記述されており、IPCメカニズム自体はファイルマッピングとWindowsメッセージを使用して実装されていることに言及する価値があります。

驚くべきことに、私はシステム全体がどのように機能するかを内部から学びました。ほぼ1年後、少し手を加えなければなりませんでした。 そして、ようやくその実装がどれほど高品質であり、APIが便利であることに気づきました。 誰がC#の下で上記のシステムに似た何かの実装を気にします-猫の下でください。



空き時間に.NET Frameworkを勉強していたので、.NETでIPCがどのように簡単/便利に実装されるかに興味がありました。 私自身ががっかりしたことに、箱からの機能は、職人のデルフィックシステムに比べて、利便性とシンプルさが著しく劣っていることに気付きました。 ここでは、.NETがデータ転送チャネルからの抽象化に重点を置いており、ネットワーク上およびプロセス間でオブジェクトを均等に移動できるという事実に基づいて、このような優れたホリバーを繁殖させることができます。 しかし、この記事のトピックはIPCなので、これを行わないようお願いします。



小さな紹介。 .NETでIPCのすべてのトリックを完全に理解することはできませんでしたが、主題の記事を読んだ後にマニュアルを吸った後 、次のオプションを使用することが現実であることに気付きました。

1. COM、

2.ファイルマッピング

3. IPCチ​​ャネル。

COMまたはファイルマッピングを使用した実装は、他の言語のアナログとほとんど変わらないため、選択は.NETの組み込みIPCメカニズムに間違いなくかかっていました。



多かれ少なかれ機能的なアプリケーションを作成しようとした後、それを使用して単純な行を送信する場合でも、両方のアプリケーション(送信側と受信側の両方)で不必要なジェスチャーが必要であることに気付きました。 その結果、プロセス間のオブジェクトのボールに対して、次のようなことをする必要があります。



サーバー:

IpcChannel serverChannel = new IpcChannel("MyServerChannel"); ChannelServices.RegisterChannel(serverChannel); RemotingConfiguration.RegisterWellKnownServiceType( typeof(IPCChannelRemoting.MyRemoteObject), "SharedObj", WellKnownObjectMode.SingleCall);
      
      





顧客:

 IpcChannel clientChanel = new IpcChannel("myClient"); ChannelServices.RegisterChannel(clientChanel); ISharedObj obj = (Remoteable.ISharedAssemblyInterface)Activator.GetObject( typeof(Remoteable.ISharedAssemblyInterface), "ipc://MyServerChannel/SharedObj ");
      
      





しかし、アプリケーションのどこでもデータ交換を使用する必要がある場合はどうでしょうか? この場合、上記のコードをどこにでも複製し、共有オブジェクトのURIを作成するためのルールを指定する必要があります。 また、別のプロセスからデータを要求するだけでなく、特定のシグナル/メッセージを受信するためにサブスクライブする必要がある場合はどうなりますか? チェックループでスラッシングするスレッド/タイマーを作成するか、WaitForSingleObject / EventWaitHandleを使用できます。 一般的に、自分で作成したアーキテクチャなしではできません。



IPCメカニズムを広範囲に使用するアプリケーションを開発した以前の経験によると、次のアプローチを使用すると非常に便利です。

-3つの主要なエンティティがあります:送信者、受信者、メッセージ。

-各受信者と送信者には独自の一意のIDがあり、メッセージの送信先です。 これらは、アプリケーションのPID、ウィンドウのハンドル、または両当事者に知られている既知の識別子に関連付けることができます。

-メッセージは、同期または非同期の任意の*タイプのフィールドを含むことができる抽象的な概念です。 これらのメッセージを交換するアプリケーションは、基になるメッセージの子孫の特定のクラスを認識する必要があります。 同期メッセージと非同期メッセージの違いは、必要に応じて要求の結果を同期メッセージに入れることができ、メッセージを処理した直後に送信者が利用できるようになることです(呼び出しから送信メソッドにスタックを返すことにより)。



結果として、結果のシステムを使用して、プロセス間でデータを送信することは

-送信者およびメッセージオブジェクトの作成、

-送信者を使用してメッセージを送信する、

-受信者のプロセスでの処理。



 using (BaseIPCDispatcher dispatcher = new BaseIPCDispatcher(slaveReceaverGUID)) { TestAsyncComplexMessage testMessage = new TestAsyncComplexMessage (ReceaverID, null); dispatcher.Dispatch(testMessage); }
      
      





別の、まあ、または同じプロセスでメッセージを受信するサブスクライブ:



 … Receiver.OnReceaveIPCMessage += OnReceaveMessage; … private void OnReceaveMessage(object sender, ReceaveMessageEventArgs e) { TestAsyncComplexMessage testAsyncMessage = e.Message as TestAsyncComplexMessage; if (testAsyncMessage != null) { // process message } }
      
      





私見、それはもう少し明らかに、柔軟で読みやすいことが判明しました。 コードは、マスター/スレーブアーキテクチャを使用した機能テストでカバーされています。



知り合いになりたい-結果はGitHubにあります

github.com/perevernihata/SimpleIPCCommSystem

Z.Y. 多分私は知らずに四角い車輪で自転車を発明したことを理解しています-しかし、それはとても楽しいです! 建設的な批判は大歓迎です。



*(非同期メッセージのシリアル化可能)。



All Articles