原文:
c# IPC实现本机进程之间的通信
IPC可以实现本地进程之间通信。这种用法不是太常见,常见的替代方案是使用wcf,remoting,web service,socket(tcp/pipe/...)等其他分布式部署方案来替代进程之间的通信。虽然不常见但也避免不了一些场景会使用该方案。
应用包含:
1)使用IPC技术实现多client与一个sever通信(不过是本机,感觉意义不大,但如果想实现本机上运行确实是一个不错的方案);
2)使用IPC技术实现订阅者和生产者分离时,一个server接收并消费消息,客户端是生产消息的。
1 1:新建一个MessageObject类库
2
3 代码如下:
4
5 using System;
6 using System.Collections.Generic;
7
8 namespace MessageObject
9 {
10 //MarshalByRefObject 允许在支持远程处理的应用程序中跨应用程序域边界访问对象。
11 public class RemoteObject : MarshalByRefObject
12 {
13 public static Queue<string> qMessage { get; set; } //使用消息队列储存消息
14
15 public string SendMessage(string message)
16 {
17 if (qMessage == null)
18 {
19 qMessage = new Queue<string>();
20 }
21 qMessage.Enqueue(message);
22
23 return message;
24 }
25 }
26 }
27 2:新建一个控制台程序,名称:IPCServer,是IPC的服务端
28 using System;
29 using System.Runtime.Remoting.Channels.Ipc;
30 using System.Runtime.Remoting.Channels;
31 using System.Runtime.Remoting;
32 using MessageObject;
33 using System.Threading;
34 using System.Collections.Generic;
35
36 namespace IPCServer
37 {
38 /// <summary>
39 /// IPC Server
40 /// </summary>
41 class Program
42 {
43 static void Main(string[] args)
44 {
45 StartServer();
46
47 Thread t = new Thread(new ThreadStart(ReceviceMessage)); //使用线程获取消息
48 t.Start();
49 }
50 private static void StartServer()
51 {
52 IpcServerChannel channel = new IpcServerChannel("ServerChannel");
53 ChannelServices.RegisterChannel(channel, false);
54 RemotingConfiguration.RegisterWellKnownServiceType(typeof(RemoteObject), "RemoteObject", WellKnownObjectMode.SingleCall);
55 Console.WriteLine("message server running...");
56 }
57 private static void ReceviceMessage()
58 {
59 while (true)
60 {
61 Queue<string> qMessage = RemoteObject.qMessage;
62 if (qMessage != null)
63 {
64 if (qMessage.Count > 0)
65 {
66 string message = qMessage.Dequeue();
67 Console.WriteLine("recevice message is:" message);
68 }
69 }
70 Thread.Sleep(1000); //每一秒获取一次
71 }
72 }
73
74 }
75 }
76 3:新建一个控制台程序,名称:IPCClient,IPC客户端
77 代码如下:
78 using System;
79 using MessageObject;
80 using System.Runtime.Remoting.Channels.Ipc;
81 using System.Runtime.Remoting.Channels;
82
83 namespace IPCClient
84 {
85 class Program
86 {
87 static void Main(string[] args)
88 {
89 RemoteObject objRemoteObject = ConnectServer();
90 Send(objRemoteObject);
91 }
92 private static void Send(RemoteObject objRemoteObject)
93 {
94 while (true)
95 {
96 Console.WriteLine("please input message...");
97 string message = Console.ReadLine();
98 try
99 {
100 objRemoteObject.SendMessage(message);
101 Console.WriteLine("send success");
102 }
103 catch (System.Runtime.Remoting.RemotingException)
104 {
105 Console.WriteLine("can not connect message server");
106 }
107 }
108 }
109 private static RemoteObject ConnectServer()
110 {
111 IpcClientChannel channel = new IpcClientChannel();
112 ChannelServices.RegisterChannel(channel, false);
113 RemoteObject objRemoteObject = (RemoteObject)Activator.GetObject(typeof(RemoteObject), "ipc://ServerChannel/RemoteObject");
114 return objRemoteObject;
115 }
116 }
117 }
View Code
使用技巧:
1)使用之间必须定义好一个进程之间通信的对象(该对象继承了MarshalByRefObject ,允许在支持远程处理的应用程序中跨应用程序域边界访问对象);
1 public class MyProcessSendObject : MarshalByRefObject
2 {
3 private string taskInfo = string.Empty;
4
5 public void Add(string taskInfo)
6 {
7 Console.WriteLine("Add:{0}", taskInfo);
8 this.taskInfo = taskInfo;
9 }
10
11 public string GetTask()
12 {
13 Console.WriteLine("GetTask:{0}", taskInfo);
14 return taskInfo;
15 }
16
17 }
2)服务端是发布了一个IPC服务,供客户端段来绑定使用;
1 //I PC(inter process communication)的功能可以实现同一台机器上的不同进程间通信。
2 static void Main(string[] args)
3 {
4 Console.WriteLine("I'm server......");
5 //Instantiate our server channel.
6 IpcChannel serverchannel = new IpcChannel("testchannel");
7 //Register the server channel.
8 ChannelServices.RegisterChannel(serverchannel, false);
9 //Register this service type.
10 RemotingConfiguration.RegisterWellKnownServiceType(typeof(MyProcessSendObject), "myObj", WellKnownObjectMode.Singleton);
13 Console.WriteLine("press Enter to exit");
14 Console.ReadLine();
15 Console.WriteLine("server stopped");
16 }
3)客户端使用时需要绑定服务端发布的地址,之后获取发布的对象(暂时可以这么理解:数据的传递和同步是通过对象序列化、反序列化),在客户端操作该对象时实际上是操作了服务端的对象。
1 static void Main(string[] args)
2 {
3 Console.WriteLine("I'm client......");
4 IpcChannel tcc = new IpcChannel();
5 ChannelServices.RegisterChannel(tcc, false);
6
7 MyProcessSendObject myObj = (MyProcessSendObject)Activator.GetObject(typeof(MyProcessSendObject), "ipc://testchannel/myObj");
8
9 Console.WriteLine("client send myvalue start");
10 myObj.Add("Task 1");
11 myObj.GetTask();
12 myObj.Add("Task 2");
13 myObj.GetTask();
14 Console.WriteLine("client send myvalue complete");
15 Console.ReadLine();
16 }
工程结构:
![]()
测试:
![]()