[Remoting专题系列] 十一:事件
生活随笔
收集整理的這篇文章主要介紹了
[Remoting专题系列] 十一:事件
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
在?Remoting?中使用?Event?主要是為了實現?CallBack?機制,讓服務器在接收到某個?"消息"?時,主動調用某個或多個客戶端的方法。
我們先看一個例子。
using?System;
using?System.Collections;
using?System.Collections.Generic;
using?System.Reflection;
using?System.Runtime.Serialization.Formatters;
using?System.Runtime.Serialization.Formatters.Binary;
using?System.Runtime.Remoting;
using?System.Runtime.Remoting.Channels;
using?System.Runtime.Remoting.Channels.Tcp;
namespace?Learn.Library.Remoting
{
??/**////?<summary>
??///?委托類型
??///?</summary>
??public?delegate?void?TestHandler();
??/**////?<summary>
??///?遠程類型
??///?</summary>
??public?class?Data?:?MarshalByRefObject
??{
????public?TestHandler?OnTest;
????public?void?Test()
????{
??????Console.WriteLine("Test(AppDomain:{0})",?AppDomain.CurrentDomain.FriendlyName);
??????if?(OnTest?!=?null)?OnTest();
????}
??}
??public?class?RemotingTest2
??{
????/**////?<summary>
????///?服務器端代碼
????///?</summary>
????static?void?Server()
????{
??????AppDomain?server?=?AppDomain.CreateDomain("server");
??????server.DoCallBack(delegate
??????{
????????BinaryServerFormatterSinkProvider?bin?=?new?BinaryServerFormatterSinkProvider();
????????bin.TypeFilterLevel?=?TypeFilterLevel.Full;
????????TcpServerChannel?channel?=?new?TcpServerChannel("server",?801,?bin);
????????ChannelServices.RegisterChannel(channel,?false);
????????RemotingConfiguration.RegisterWellKnownServiceType(typeof(Data),?"data",?
??????????WellKnownObjectMode.Singleton);
??????});
????}
????/**////?<summary>
????///?客戶端代碼
????///?</summary>
????static?void?Client()
????{
??????TcpClientChannel?channel?=?new?TcpClientChannel();
??????ChannelServices.RegisterChannel(channel,?false);
??????RemotingConfiguration.RegisterWellKnownClientType(typeof(Data),?"tcp://localhost:801/data");
??????Data?data?=?new?Data();
??????data.OnTest?+=?delegate?
??????{?
????????Console.WriteLine("OnTest(AppDomain:{0})",?AppDomain.CurrentDomain.FriendlyName);?
??????};
??????data.Test();
????}
????static?void?Main()
????{
??????Server();
??????Client();
????}
??}
}
輸出:
Test(AppDomain:server)
OnTest(AppDomain:server)
運行結果表明客戶端事件方法?OnTest?被順利執行。只不過結果有點問題,OnTest?是在服務器程序域內執行,這顯然和我們設想服務器去通知客戶端有所出入。這種方式實質上是將客戶端委托方法一起序列化為消息傳遞到服務器端,然后在服務器應用程序域被執行,因此客戶端是無法接收到所謂?"回調消息"?的。
要實現我們所需要的?Remoting?Event,需要做如下步驟:
1.?采取所謂?Duplex?方式。也就是說在客戶端和服務器同時啟用?ServerChannel?和?ClientChannel,因此我們需要使用?HttpChannel?或?TcpChannel。
2.?客戶端事件方法應該是一個繼承自?MarshalByRefObject?類型的實例方法。因為服務器是通過創建客戶端的?MBR?SAO?對象來實現回調的。
3.?缺省情況下,Delegate?無法被序列化,因此我們需要將服務器的?Formatter.TypeFilterLevel?設置為?Full。
修改后的代碼。
using?System;
using?System.Collections;
using?System.Collections.Generic;
using?System.Reflection;
using?System.Runtime.Serialization.Formatters;
using?System.Runtime.Serialization.Formatters.Binary;
using?System.Runtime.Remoting;
using?System.Runtime.Remoting.Channels;
using?System.Runtime.Remoting.Channels.Tcp;
namespace?Learn.Library.Remoting
{
??/**////?<summary>
??///?委托類型
??///?</summary>
??public?delegate?void?TestHandler();
??/**////?<summary>
??///?遠程類型
??///?</summary>
??public?class?Data?:?MarshalByRefObject
??{
????public?TestHandler?OnTest;
????public?void?Test()
????{
??????Console.WriteLine("Test(AppDomain:{0})",?AppDomain.CurrentDomain.FriendlyName);
??????if?(OnTest?!=?null)?OnTest();
????}
??}
??/**////?<summary>
??///?客戶端遠程類型
??///?</summary>
??public?class?ClientData?:?MarshalByRefObject
??{
????public?void?OnTestMethod()
????{
??????Console.WriteLine("Test(AppDomain:{0})",?AppDomain.CurrentDomain.FriendlyName);
????}
??}
??public?class?RemotingTest2
??{
????/**////?<summary>
????///?服務器端代碼
????///?</summary>
????static?void?Server()
????{
??????AppDomain?server?=?AppDomain.CreateDomain("server");
??????server.DoCallBack(delegate
??????{
????????BinaryClientFormatterSinkProvider?cbin?=?new?BinaryClientFormatterSinkProvider();
????????BinaryServerFormatterSinkProvider?sbin?=?new?BinaryServerFormatterSinkProvider();
????????sbin.TypeFilterLevel?=?TypeFilterLevel.Full;
????????Hashtable?properties?=?new?Hashtable();
????????properties["port"]?=?801;
????????TcpChannel?channel?=?new?TcpChannel(properties,?cbin,?sbin);
????????ChannelServices.RegisterChannel(channel,?false);
????????RemotingConfiguration.RegisterWellKnownServiceType(typeof(Data),?"data",?
??????????WellKnownObjectMode.Singleton);
??????});
????}
????/**////?<summary>
????///?客戶端代碼
????///?</summary>
????static?void?Client()
????{
??????TcpChannel?channel?=?new?TcpChannel(802);
??????ChannelServices.RegisterChannel(channel,?false);
??????RemotingConfiguration.RegisterWellKnownClientType(typeof(Data),?"tcp://localhost:801/data");
??????Data?data?=?new?Data();
??????data.OnTest?+=?new?ClientData().OnTestMethod;
??????data.Test();
????}
????static?void?Main()
????{
??????Server();
??????Client();
????}
??}
}
我們先看一個例子。
using?System;
using?System.Collections;
using?System.Collections.Generic;
using?System.Reflection;
using?System.Runtime.Serialization.Formatters;
using?System.Runtime.Serialization.Formatters.Binary;
using?System.Runtime.Remoting;
using?System.Runtime.Remoting.Channels;
using?System.Runtime.Remoting.Channels.Tcp;
namespace?Learn.Library.Remoting
{
??/**////?<summary>
??///?委托類型
??///?</summary>
??public?delegate?void?TestHandler();
??/**////?<summary>
??///?遠程類型
??///?</summary>
??public?class?Data?:?MarshalByRefObject
??{
????public?TestHandler?OnTest;
????public?void?Test()
????{
??????Console.WriteLine("Test(AppDomain:{0})",?AppDomain.CurrentDomain.FriendlyName);
??????if?(OnTest?!=?null)?OnTest();
????}
??}
??public?class?RemotingTest2
??{
????/**////?<summary>
????///?服務器端代碼
????///?</summary>
????static?void?Server()
????{
??????AppDomain?server?=?AppDomain.CreateDomain("server");
??????server.DoCallBack(delegate
??????{
????????BinaryServerFormatterSinkProvider?bin?=?new?BinaryServerFormatterSinkProvider();
????????bin.TypeFilterLevel?=?TypeFilterLevel.Full;
????????TcpServerChannel?channel?=?new?TcpServerChannel("server",?801,?bin);
????????ChannelServices.RegisterChannel(channel,?false);
????????RemotingConfiguration.RegisterWellKnownServiceType(typeof(Data),?"data",?
??????????WellKnownObjectMode.Singleton);
??????});
????}
????/**////?<summary>
????///?客戶端代碼
????///?</summary>
????static?void?Client()
????{
??????TcpClientChannel?channel?=?new?TcpClientChannel();
??????ChannelServices.RegisterChannel(channel,?false);
??????RemotingConfiguration.RegisterWellKnownClientType(typeof(Data),?"tcp://localhost:801/data");
??????Data?data?=?new?Data();
??????data.OnTest?+=?delegate?
??????{?
????????Console.WriteLine("OnTest(AppDomain:{0})",?AppDomain.CurrentDomain.FriendlyName);?
??????};
??????data.Test();
????}
????static?void?Main()
????{
??????Server();
??????Client();
????}
??}
}
輸出:
Test(AppDomain:server)
OnTest(AppDomain:server)
運行結果表明客戶端事件方法?OnTest?被順利執行。只不過結果有點問題,OnTest?是在服務器程序域內執行,這顯然和我們設想服務器去通知客戶端有所出入。這種方式實質上是將客戶端委托方法一起序列化為消息傳遞到服務器端,然后在服務器應用程序域被執行,因此客戶端是無法接收到所謂?"回調消息"?的。
要實現我們所需要的?Remoting?Event,需要做如下步驟:
1.?采取所謂?Duplex?方式。也就是說在客戶端和服務器同時啟用?ServerChannel?和?ClientChannel,因此我們需要使用?HttpChannel?或?TcpChannel。
2.?客戶端事件方法應該是一個繼承自?MarshalByRefObject?類型的實例方法。因為服務器是通過創建客戶端的?MBR?SAO?對象來實現回調的。
3.?缺省情況下,Delegate?無法被序列化,因此我們需要將服務器的?Formatter.TypeFilterLevel?設置為?Full。
修改后的代碼。
using?System;
using?System.Collections;
using?System.Collections.Generic;
using?System.Reflection;
using?System.Runtime.Serialization.Formatters;
using?System.Runtime.Serialization.Formatters.Binary;
using?System.Runtime.Remoting;
using?System.Runtime.Remoting.Channels;
using?System.Runtime.Remoting.Channels.Tcp;
namespace?Learn.Library.Remoting
{
??/**////?<summary>
??///?委托類型
??///?</summary>
??public?delegate?void?TestHandler();
??/**////?<summary>
??///?遠程類型
??///?</summary>
??public?class?Data?:?MarshalByRefObject
??{
????public?TestHandler?OnTest;
????public?void?Test()
????{
??????Console.WriteLine("Test(AppDomain:{0})",?AppDomain.CurrentDomain.FriendlyName);
??????if?(OnTest?!=?null)?OnTest();
????}
??}
??/**////?<summary>
??///?客戶端遠程類型
??///?</summary>
??public?class?ClientData?:?MarshalByRefObject
??{
????public?void?OnTestMethod()
????{
??????Console.WriteLine("Test(AppDomain:{0})",?AppDomain.CurrentDomain.FriendlyName);
????}
??}
??public?class?RemotingTest2
??{
????/**////?<summary>
????///?服務器端代碼
????///?</summary>
????static?void?Server()
????{
??????AppDomain?server?=?AppDomain.CreateDomain("server");
??????server.DoCallBack(delegate
??????{
????????BinaryClientFormatterSinkProvider?cbin?=?new?BinaryClientFormatterSinkProvider();
????????BinaryServerFormatterSinkProvider?sbin?=?new?BinaryServerFormatterSinkProvider();
????????sbin.TypeFilterLevel?=?TypeFilterLevel.Full;
????????Hashtable?properties?=?new?Hashtable();
????????properties["port"]?=?801;
????????TcpChannel?channel?=?new?TcpChannel(properties,?cbin,?sbin);
????????ChannelServices.RegisterChannel(channel,?false);
????????RemotingConfiguration.RegisterWellKnownServiceType(typeof(Data),?"data",?
??????????WellKnownObjectMode.Singleton);
??????});
????}
????/**////?<summary>
????///?客戶端代碼
????///?</summary>
????static?void?Client()
????{
??????TcpChannel?channel?=?new?TcpChannel(802);
??????ChannelServices.RegisterChannel(channel,?false);
??????RemotingConfiguration.RegisterWellKnownClientType(typeof(Data),?"tcp://localhost:801/data");
??????Data?data?=?new?Data();
??????data.OnTest?+=?new?ClientData().OnTestMethod;
??????data.Test();
????}
????static?void?Main()
????{
??????Server();
??????Client();
????}
??}
}
轉載于:https://www.cnblogs.com/nbwzy/archive/2007/06/05/771532.html
總結
以上是生活随笔為你收集整理的[Remoting专题系列] 十一:事件的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 《DNF》失去作用的物品汇总 混沌王牌系
- 下一篇: 对一个整数按位反转