[Remoting] 十一:事件(收藏转帖http://www.rainsts.net/article.asp?id=419)
来源:互联网 发布:湖南软件评测中心学费 编辑:程序博客网 时间:2024/04/30 02:53
在 Remoting 中使用 Event 主要是为了实现 CallBack 机制,让服务器在接收到某个 "消息" 时,主动调用某个或多个客户端的方法。
我们先看一个例子。
输出:
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。
修改后的代码。
输出:
Test...(AppDomain:server)
Test...(AppDomain:Test.exe)
我们先看一个例子。
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();
}
}
}
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.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();
}
}
}
输出:
Test...(AppDomain:server)
Test...(AppDomain:Test.exe)
- [Remoting] 十一:事件(收藏转帖http://www.rainsts.net/article.asp?id=419)
- [Remoting] 五:信道(收藏转帖http://www.rainsts.net/article.asp?id=412)
- [Remoting] 十二:配置文件(收藏转帖http://www.rainsts.net/article.asp?id=420)
- NET Remoting一,二(收藏转帖http://www.rainsts.net/article.asp?id=408)
- [Remoting] 三:激活模式(收藏转帖http://www.rainsts.net/article.asp?id=410)
- [Remoting] 四:生存期租约(收藏转帖http://www.rainsts.net/article.asp?id=411)
- [Remoting] 六:异步调用(收藏转帖http://www.rainsts.net/article.asp?id=413)
- [Remoting] 七:调用上下文(收藏转帖http://www.rainsts.net/article.asp?id=414)
- [Remoting] 八:元数据(收藏转帖http://www.rainsts.net/article.asp?id=415)
- [Remoting] 九:动态发布(收藏转帖http://www.rainsts.net/article.asp?id=416)
- [Remoting] 十:追踪服务(收藏转帖http://www.rainsts.net/article.asp?id=417)
- Message Queuing(收藏转帖http://www.rainsts.net/article.asp?id=418)
- 动态调用 WebService (收藏转贴http://www.rainsts.net/article.asp?id=304)
- [ASP.NET 优化] IIS6 Gziphttp://www.rainsts.net/article.asp?id=531
- 从雨痕老大的博客上转来的 http://www.rainsts.net/article.asp?id=1066 读书人偷书不算窃 :)
- asp.net控件开发基础 来源:http://www.clingingboy.com/blog/article.asp?id=258
- WebConfirm控件(转自http://www.evget.com/view/article/viewArticle.asp?article=961)
- WebConfirm控件(转自http://www.evget.com/view/article/viewArticle.asp?article=961)
- First
- Linux 与你同行!
- [Remoting] 十:追踪服务(收藏转帖http://www.rainsts.net/article.asp?id=417)
- Message Queuing(收藏转帖http://www.rainsts.net/article.asp?id=418)
- (转)QNX-从4到6简单入门
- [Remoting] 十一:事件(收藏转帖http://www.rainsts.net/article.asp?id=419)
- [Remoting] 十二:配置文件(收藏转帖http://www.rainsts.net/article.asp?id=420)
- 用javascript动态调整iframe高度【兼容ie&FF】【转】
- 开博客
- 中午了
- .NET开源项目
- CLucene开发杂记(1)
- 数据库设计心得
- 无法创建DOMDocument对象,请检查是否安装了MS XML Parser 运行库!