Remoting 自定义通道(可加密通讯)
1 服务端在调用 System.Runtime.Remoting.RemotingConfiguration.Configure(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile, false);时,会创建服务器提供程序实例(调用两参的构造函数)。
然后调用提供程序的CreateSink方法创建接收器(在此之前系统会赋值Next下一个接受器)。
2 客户端在调用 System.Runtime.Remoting.RemotingConfiguration.Configure(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile, false);时,会创建服务器提供程序实例(调用两参的构造函数)。
然后调用提供程序的CreateSink方法创建接收器(在此之前系统会赋值Next下一个接受器)。
)。
3 客户端在使用远程对象时会经过客户端的信道接收器处理(ProcessMessage方法),再通过服务端的信道接收器处理(ProcessMessage方法)。
4 客户端配置文件clientProviders元素下的formatter 包含要插入到信道接收器调用链中的格式化程序接收器。可出现一次(作为第一个接收器)。如果没有配置此项。第一个接受器就必须实现IMessageSink接口。
服务端
信道:
class SecureServerChannelSink:BaseChannelSinkWithProperties,IServerChannelSink { /// <summary> 接受器链表中的下一个接收器 </summary> private IServerChannelSink _next; /// <summary> /// 构造函数 /// 初始化安全通道接收器 /// </summary> public SecureServerChannelSink(IServerChannelSink nextSink) { //设置下一个接收器 _next = nextSink; } /// <summary> /// 请求从当前接收器对异步发送的方法调用的响应进行处理 /// </summary> public void AsyncProcessResponse(IServerResponseChannelSinkStack sinkStack, object state, IMessage msg, ITransportHeaders headers, Stream stream) { //当前接收器处理业务逻辑.... //下一个接收器处理 _next.AsyncProcessResponse(sinkStack, state, msg, headers, stream); } /// <summary> /// 返回提供的响应消息将序列化到其上的 System.IO.Stream /// 需要创建响应流时将调用此方法 /// </summary> public Stream GetResponseStream(IServerResponseChannelSinkStack sinkStack, object state, IMessage msg, ITransportHeaders headers) { //当前接收器处理业务逻辑.... //下一个接收器处理 return _next.GetResponseStream(sinkStack, state, msg, headers); } /// <summary> /// 获取服务器接收器链中的下一个服务器信道接收器 /// </summary> public IServerChannelSink NextChannelSink { get { return _next; } set { _next = value; } } /// <summary> /// 现有的接收器的请求处理 /// 代理的工作就是将对其进行的方法调用转换为消息对象。 通过对消息接收器对象调用 ProcessMessage,将该消息对象(实现 IMessage 接口)从客户端传递到服务器端。 消息接收器以如下方式链接在一起:每个消息接收器负责在执行完它的工作后对下一个消息接收器调用 ProcessMessage。 例如,一个与同步相关的消息接收器可以使锁被获取或释放,然后被委托给下游的消息接收器。 /// </summary> /// <param name="sinkStack">调用了当前接收器的信道接收器的堆栈</param> /// <param name="requestMsg">包含请求的消息</param> /// <param name="requestHeaders">从来自客户端的传入消息中检索到的标头</param> /// <param name="requestStream">需要进行处理并传递到反序列化接收器的流</param> /// <param name="responseMsg">响应消息的</param> /// <param name="responseHeaders">响应的头信息</param> /// <param name="responseStream">响应的流</param> /// <returns>返回服务器消息处理状态枚举</returns> public ServerProcessing ProcessMessage(IServerChannelSinkStack sinkStack, IMessage requestMsg, ITransportHeaders requestHeaders, Stream requestStream, out IMessage responseMsg, out ITransportHeaders responseHeaders, out Stream responseStream) { //当前接收器处理业务逻辑.... //下一个接收器处理 return _next.ProcessMessage(sinkStack, requestMsg, requestHeaders, requestStream, out responseMsg, out responseHeaders, out responseStream); }
信道提供程序:
class SecureServerChannelSinkProvider : IServerChannelSinkProvider { /// <summary>接收器链表中下一个接收器提供器</summary> private IServerChannelSinkProvider _next = null; /// <summary> /// 构造函数 /// 初始化接收器提供器 /// 为了使用基于文件的配置提供程序,需要使用这个构造函数。它不需要做任何事情,除非您想使用参数中的信息。 /// </summary> /// <param name="properties">在配置文件中的参数描述</param> /// <param name="providerData">接受提供器数据</param> public SecureServerChannelSinkProvider(IDictionary properties, ICollection providerData) { foreach (DictionaryEntry entry in properties) { switch ((string)entry.Key) { //这里可以获取配置文件中的参数 default: break; } } } #region IServerChannelSinkProvider接口实现方法 /// <summary> /// 创建接收器链 /// </summary> /// <param name="channel">要为其创建信道接收器链的信道</param> /// <returns>新生成的信道接收器链中的第一个接收器,或 null(指示此提供程序将不会或不能为此终结点提供连接)</returns> public IServerChannelSink CreateSink(IChannelReceiver channel) { IServerChannelSink nextSink = null; if (_next != null) { //在链表中的下一个接收器提供器创建下一个接收器对象 if ((nextSink = _next.CreateSink(channel)) == null) return null; } //创建本接受器并将上一个接收器的信息传送给它 return new SecureServerChannelSink(nextSink); } /// <summary> /// 返回与当前接收器关联的信道的信道数据 /// </summary> public void GetChannelData(IChannelDataStore channelData) { } /// <summary> /// 获取或设置信道接收器提供程序链中的下一个接收器提供程序 /// </summary> public IServerChannelSinkProvider Next { get { return _next; } set { _next = value; } } #endregion
服务端 配置文件
<?xml version="1.0" encoding="utf-8" ?> <configuration> <system.runtime.remoting> <application> <channels> <channel ref="tcp" port="8086"> <serverProviders> <provider type="Zytk.AppConnect.SecureServerChannelSinkProvider,AppConnect" ...此处可以添加参数,在提供程序构造函数中获取到值/> <formatter ref="binary" /> </serverProviders> </channel> </channels> <service> <wellknown type="..." objectUri="..." mode="SingleCall" /> </service> </application> </system.runtime.remoting> </configuration>
客户端
客户端信道:
1 class SecureClientChannelSink : BaseChannelSinkWithProperties, IClientChannelSink 2 { 3 //实现IClientChannelSink接口即可类似服务端 4 }
客户端信息提供程序:
1 class SecureClientChannelSinkProvider:IClientChannelSinkProvider 2 { 3 //实现IClientChannelSinkProvider接口即可,类似服务端 4 }
配置文件
1 <?xml version="1.0" encoding="utf-8" ?> 2 <configuration> 3 <system.runtime.remoting> 4 <application> 5 <channels> 6 <channel ref="tcp"> 7 <clientProviders> 8 <!--formatter 包含要插入到信道接收器调用链中的格式化程序接收器。可出现一次。 9 如果没有配置此项。第一个接受器就必须实现IMessageSink接口--> 10 <formatter ref="binary"/> 11 <provider type="Zytk.AppConnect.SecureClientChannelSinkProvider,AppConnect"/> 12 </clientProviders> 13 </channel> 14 </channels> 15 <client> 16 <wellknown type="..." url="tcp://localhost:8086/..." /> 17 </client> 18 </application> 19 </system.runtime.remoting> 20 </configuration>