- - PR -
プロセス間通信(IPC) Remortingについて
1
投稿者 | 投稿内容 |
---|---|
|
投稿日時: 2009-02-25 13:22
VB.NETでプロセス間通信を行いたいのですが、うまくいきませんどこがいけないのでしょうか?
サーバーを立ち上げ、 クライアント側から、メッセージを送信しようとした場合に、 IPCポートに接続できませんとエラーが出てしまいます。 参考サイト http://katamari.jp/index.php?dev%2Fvb%2F.NET%20Remoting%A4%F2%BB%C8%CD%D1%A4%B7%A4%BF%A5%D7%A5%ED%A5%BB%A5%B9%B4%D6%C4%CC%BF%AE ソース サーバー側 Private Const Port As Integer = 8088 Private Const ObjectUri As String = "RemoteObj" Private mChannel As IpcChannel Private mRemoteObject As RemoteObject Private Sub IPC() Dim provider As BinaryServerFormatterSinkProvider Dim props As IDictionary provider = New BinaryServerFormatterSinkProvider provider.TypeFilterLevel = Runtime.Serialization.Formatters.TypeFilterLevel.Full props = New Hashtable props("port") = Port Try '// サーバチャネル生成 mChannel = New IpcChannel(props, Nothing, provider) '// チャネル登録 ChannelServices.RegisterChannel(mChannel, True) Catch exSocket As System.Net.Sockets.SocketException Console.WriteLine(exSocket.ToString) Exit Sub Catch ex As Exception Console.WriteLine(ex.ToString) Exit Sub End Try '// RemoteObjectインスタンス生成 mRemoteObject = New RemoteObject '//メッセージを受信する関数を指定 AddHandler mRemoteObject.ReceiveMessage, AddressOf ReceiveMessage '// RemotingServices.Marshal(mRemoteObject, ObjectUri) End Sub '// FormClosed Private Sub IpcEnd() Try If Not mChannel Is Nothing Then '//チャネルの登録を解除 ChannelServices.UnregisterChannel(mChannel) End If Catch ex As Exception Console.WriteLine(ex.ToString) End Try End Sub '// メッセージ受信 Private Sub ReceiveMessage(ByVal msg As String) Console.WriteLine("Server ReceiveMessage: {0}", msg) End Sub クライアント側 Private Const ObjectUri As String = "RemoteObj" Private Const TypeName As String = "RemoteObject, RemoteObject" Private Const Port As Integer = 8088 Private mChannel As IPCChannel Private mRemoteObject As RemoteObject '// FormLoad Private Sub Ipc() '// クライアントチャネルのみアクティブなIPCChannelインスタンス生成 mChannel = New IPCChannel Try '// チャネル登録 ChannelServices.RegisterChannel(mChannel, False) Catch ex As Exception Console.WriteLine(ex.ToString) Exit Sub End Try Dim a As New RemoteObject Try '// RemoteObjectインスタンス生成 '// この時点でServerプログラムが起動していなくても例外は発生しない mRemoteObject = CType(Activator.GetObject( _ a.GetType, _ "IPC://localhost:" & Port.ToString & "/" & ObjectUri), _ RemoteObject) Catch ex As Exception Console.WriteLine(ex.ToString) Exit Sub End Try End Sub '// FromClosed Private Sub IPCEnd() Try If Not mChannel Is Nothing Then '//チャネルの登録を解除 ChannelServices.UnregisterChannel(mChannel) End If Catch ex As Exception Console.WriteLine(ex.ToString) End Try End Sub '// Send Button クリック Private Sub msgSend(ByRef strbuf As String) If mRemoteObject Is Nothing Then Exit Sub End If Try '// 送信 mRemoteObject.SendMessage(strbuf) Catch ex As Exception Console.WriteLine(ex.ToString) End Try End Sub リモートオブジェクト Public Class RemoteObject Inherits MarshalByRefObject Public Delegate Sub delReceiveMessage(ByVal str As String) Public Event ReceiveMessage As delReceiveMessage Public Sub SendMessage(ByVal str As String) RaiseEvent ReceiveMessage(str) End Sub End Class |
|
投稿日時: 2009-02-27 01:22
こんにちわ。丁度IPCを試していたところで、大体思ったように動くので良かったら参考にして下さい。と、いいましてもC#なので読みなおしていただければいけませんが。。。また、あかりさんが示している方法とやや違うのですがご了承を。
プログラムにはWindowsサービスとWinアプリの2つがあります。 WindowsサービスがIPCのサーバになります。 クライアントはWinアプリとWindowsサービスの2つがあります。これがキモです。 サーバとクライアントが通信するのかと思ってたのですが、通信するのは クライアントとクライアントで、サーバはその場を作る、みたいです。これについては ここの投稿にもありました。 // // Windowsサービス // 仕様 // 1. OnStartで、IpcServerChannelでサーバーを登録 // 2. ACLで、AdministratorとPowerUserのみ許可 // 3. IpcClientChannelでWinアプリと通信するクライアントの登録 // 4. IPCで現在の時刻を共有する protected override void OnStart(string[] args) { // TODO: サービスを開始するためのコードをここに追加します。 #region "ACL" IDictionary props = new Hashtable(); props["portName"] = "remote"; // ACL // Local administrators sid SecurityIdentifier localAdminSid = new SecurityIdentifier( WellKnownSidType.BuiltinAdministratorsSid, null); // Local Power users sid SecurityIdentifier powerUsersSid = new SecurityIdentifier( WellKnownSidType.BuiltinPowerUsersSid, null); DiscretionaryAcl dacl = new DiscretionaryAcl(false, false, 1); // Allow acces only from local administrators and power users dacl.AddAccess(AccessControlType.Allow, localAdminSid, -1, InheritanceFlags.None, PropagationFlags.None); dacl.AddAccess(AccessControlType.Allow, powerUsersSid, -1, InheritanceFlags.None, PropagationFlags.None); CommonSecurityDescriptor securityDescriptor = new CommonSecurityDescriptor(false, false, ControlFlags.GroupDefaulted | ControlFlags.OwnerDefaulted | ControlFlags.DiscretionaryAclPresent, null, null, null, dacl); #endregion // IPC Channelを作成 IpcServerChannel servChannel = new IpcServerChannel( props, null, securityDescriptor); // リモートオブジェクトを登録 ChannelServices.RegisterChannel(servChannel, false); RemotingConfiguration.RegisterWellKnownServiceType(typeof (CopyNow), "copynow", WellKnownObjectMode.Singleton); // クライアント IpcClientChannel clientChannel = new IpcClientChannel(); ChannelServices.RegisterChannel(clientChannel, false); try { RemotingConfiguration.RegisterWellKnownClientType(typeof(CopyNow), "ipc://remote/copynow"); } catch(Exception e) { } // IPCで共有するオブジェクトの生成 // m_copyNowはフィールド m_copyNow = new CopyNow(); m_copyNow.Msg = "Hi! Client. " + DateTime.Now.ToString(); } // // IPCで共有するオブジェクト // public class CopyNow : MarshalByRefObject { static string m_msg = ""; public CopyNow() { } public string Msg { set { m_msg = value; } get { return m_msg; } } } // // Winアプリ // 仕様 // 1. ウィンドウ生成時にIpcClientChannelを登録 // 2. タイマーで定期的にサーバから情報を取得 public partial class Form1 : Form { // IPC CopyNow m_copyNow = new CopyNow(); public Form1() { // IPC IpcClientChannel clientChannel = new IpcClientChannel(); ChannelServices.RegisterChannel(clientChannel); try { RemotingConfiguration.RegisterWellKnownClientType(typeof(CopyNow), "ipc://remote/copynow"); } catch(Exception e) { Console.WriteLine("2: " + e.Message); } } // // 例として、タイマーを使って定期的にサーバの情報を取得する // private void tmrServerIPC_Tick(object sender, EventArgs e) { if (m_copyNow != null) { string msg = m_copyNow.Msg; Console.WriteLine("> " + msg); } } この例ではサーバを登録したら即座にクライアントで情報を書き込んでいますが、実プログラムでは、タイマーで定期的に書き込んで、Winアプリ側も定期的に取得しています。参考になれば幸いです。 |
|
投稿日時: 2009-02-27 11:31
すけきよK20A様回答ありがとうございます。
難しくて、なかなか理解できませんでした。 サービスの登録から躓いてしまいました。 >サーバとクライアントが通信するのかと思ってたのですが、通信するのは クライアントとクライアントで、サーバはその場を作る、みたいです。これについては ここの投稿にもありました。 私もその投稿は拝見させていただきました、その折参考サイトの書き込みを見て、できるのではと考えたのですが、うまくいきませんでした。 サーバー対クライアントがうまくいきましたので、ご報告いたします。 サーバー側 'パイプ名にあたるため任意名でよい、どらえもんと入力しても成功 'クライアントと同じにすること。 Private Const Port As Integer = 8088 '通信クラス名任意名でよい、クライアントと同じにすること。 Private Const ObjectUri As String = "RemoteObj" 'System.Runtime.Remotingを参照に追加 Private mChannel As IpcServerChannel 'クラスライブラリーに分けないと、共有オブジェクトは行えない Private mRemoteObject As ClassLibrary1.RemoteObject Private Sub IPC() Try '// サーバチャネル生成 '// チャネル登録 mChannel = New System.Runtime.Remoting.Channels.Ipc.IpcServerChannel(Port) System.Runtime.Remoting.Channels.ChannelServices.RegisterChannel(mChannel, True) System.Runtime.Remoting.RemotingConfiguration.RegisterWellKnownServiceType(GetType(ClassLibrary1.RemoteObject), GetType(ClassLibrary1.RemoteObject).Name, Runtime.Remoting.WellKnownObjectMode.SingleCall) Catch ex As Exception Console.WriteLine(ex.ToString) Exit Sub End Try '// RemoteObjectインスタンス生成 mRemoteObject = New ClassLibrary1.RemoteObject '//メッセージを受信する関数を指定 AddHandler mRemoteObject.ReceiveMessage, AddressOf ReceiveMessage '// RemotingServices.Marshal(mRemoteObject, ObjectUri) End Sub '// FormClosed Private Sub IpcEnd() Try If Not mChannel Is Nothing Then '//チャネルの登録を解除 ChannelServices.UnregisterChannel(mChannel) End If Catch ex As Exception 'Console.WriteLine(ex.ToString) End Try End Sub '// メッセージ受信 Private Sub ReceiveMessage(ByVal msg As String) Console.WriteLine("Server ReceiveMessage: {0}", msg) str = msg End Sub クライアント側 Private Const ObjectUri As String = "RemoteObj" Private Const Port As Integer = 8088 Private mChannel As System.Runtime.Remoting.Channels.Ipc.IpcClientChannel Private mRemoteObject As ClassLibrary1.RemoteObject '// FormLoad Private Sub Ipc() Try '// チャネル登録 mChannel = New System.Runtime.Remoting.Channels.Ipc.IpcClientChannel System.Runtime.Remoting.Channels.ChannelServices.RegisterChannel(mChannel, True) Dim obj As Object = Activator.GetObject(GetType(ClassLibrary1.RemoteObject), "ipc://" & Port & "/" & ObjectUri) mRemoteObject = CType(obj, ClassLibrary1.RemoteObject) Catch ex As Exception Console.WriteLine(ex.ToString) Exit Sub End Try End Sub '// FromClosed Private Sub IPCEnd() Try If Not mChannel Is Nothing Then '//チャネルの登録を解除 ChannelServices.UnregisterChannel(mChannel) End If Catch ex As Exception Console.WriteLine(ex.ToString) End Try End Sub '// Send Button クリック Private Sub msgSend(ByRef strbuf As String) If mRemoteObject Is Nothing Then Exit Sub End If Try '// 送信 mRemoteObject.SendMessage(strbuf) Catch ex As Exception Console.WriteLine(ex.ToString) End Try End Sub クラスライブラリ Public Class RemoteObject Inherits MarshalByRefObject Public Delegate Sub delReceiveMessage(ByVal str As String) Public Event ReceiveMessage As delReceiveMessage Public Sub SendMessage(ByVal str As String) RaiseEvent ReceiveMessage(str) End Sub End Class |
1