调用上下文(CallContext)提供了用于存储属性集的数据槽,可以让我们在调用服务器方法时将一些额外数据一并传送过去。当然,这些额外数据有点限制,就是必须要实现 ILogicalThreadAffinative 接口。调用上下文在应用程序域边界被克隆,其数据槽不在其他逻辑线程上的调用上下文之间共享。
我们利用这个特性写一个简单的身份验证例子。
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Threading;
using System.Security.Permissions;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.CompilerServices;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Lifetime;
using System.Runtime.Remoting.Services;
namespace Learn.Library.Remoting
{
public class RemotingTest2
{
/// <summary>
/// 身份验证类型
/// </summary>
[Serializable]
public class Identity : ILogicalThreadAffinative
{
private string username;
private string password;
public Identity(string username, string password)
{
this.username = username;
this.password = password;
}
public string Username
{
get { return username; }
set { username = value; }
}
public string Password
{
get { return password; }
set { password = value; }
}
}
/// <summary>
/// 远程类型
/// </summary>
public class Data : MarshalByRefObject
{
public void Test()
{
// 执行身份验证
Identity identity = CallContext.GetData("identity") as Identity;
if (identity != null && identity.Username == "user1" && identity.Password == "pass")
{
Console.WriteLine("Test AppDomain:{0}", AppDomain.CurrentDomain.FriendlyName);
}
}
}
/// <summary>
/// 服务器端代码
/// </summary>
static void Server()
{
AppDomain server = AppDomain.CreateDomain("server");
server.DoCallBack(delegate
{
TcpServerChannel channel = new TcpServerChannel(801);
ChannelServices.RegisterChannel(channel, false);
RemotingConfiguration.ApplicationName = "test";
RemotingConfiguration.RegisterActivatedServiceType(typeof(Data));
});
}
/// <summary>
/// 客户端代码
/// </summary>
static void Client()
{
TcpClientChannel channel = new TcpClientChannel();
ChannelServices.RegisterChannel(channel, false);
RemotingConfiguration.RegisterActivatedClientType(typeof(Data), "tcp://localhost:801/test");
// 传送身份验证数据
CallContext.SetData("identity", new Identity("user1", "pass"));
Data data = new Data();
data.Test();
}
static void Main()
{
Server();
Client();
}
}
}
数据槽中的数据可以双向传输,也就是说我们可以从服务器返回更多的信息给客户端。
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Threading;
using System.Security.Permissions;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.CompilerServices;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Lifetime;
using System.Runtime.Remoting.Services;
namespace Learn.Library.Remoting
{
public class RemotingTest2
{
[Serializable]
public class ServerTime : ILogicalThreadAffinative
{
private DateTime time;
public ServerTime(DateTime time)
{
this.time = time;
}
public DateTime Time
{
get { return time; }
}
}
/// <summary>
/// 远程类型
/// </summary>
public class Data : MarshalByRefObject
{
public void Test()
{
CallContext.SetData("ExInfo", new ServerTime(DateTime.Now));
Console.WriteLine("Test AppDomain:{0}", AppDomain.CurrentDomain.FriendlyName);
}
}
/// <summary>
/// 服务器端代码
/// </summary>
static void Server()
{
AppDomain server = AppDomain.CreateDomain("server");
server.DoCallBack(delegate
{
TcpServerChannel channel = new TcpServerChannel(801);
ChannelServices.RegisterChannel(channel, false);
RemotingConfiguration.ApplicationName = "test";
RemotingConfiguration.RegisterActivatedServiceType(typeof(Data));
});
}
/// <summary>
/// 客户端代码
/// </summary>
static void Client()
{
TcpClientChannel channel = new TcpClientChannel();
ChannelServices.RegisterChannel(channel, false);
RemotingConfiguration.RegisterActivatedClientType(typeof(Data), "tcp://localhost:801/test");
Data data = new Data();
data.Test();
Console.WriteLine((CallContext.GetData("ExInfo") as ServerTime).Time);
}
static void Main()
{
Server();
Client();
}
}
}
分享到:
相关推荐
自定义标头可用于在发送方和接收方之间传递数据,例如跟踪信息或安全上下文数据。 使用BeforeHandleRequestResponseAsync和AfterHandleRequestResponseAsync操作,可以应用其他日志记录来监视远程调用之间的流。 ...
第11章:上下文与拦截 .NET组件服务 .NET上下文 自定义组件服务 第12章:安全 .NET安全架构 配置权限 编程式安全 Visual Studio 2005与安全 基于主体的安全 其他安全问题 附录A:基于接口的Web服务 附录B:统一...
45.swtich是否能作用在byte上,是否能作用在long上,是否能作用在String上? 答:switch(expr1)中,expr1是一个整数表达式。因此传递给 switch 和 case 语句的参数应该是 int、 short、 char 或者 byte。long,...
13.4 管理集成测试中的应用上下文 520 13.4.1 问题 520 13.4.2 解决方案 520 13.4.3 工作原理 521 13.5 向集成测试注入测试夹具 526 13.5.1 问题 526 13.5.2 解决方案 526 13.5.3 工作原理 527 13.6...
13.4 管理集成测试中的应用上下文 520 13.4.1 问题 520 13.4.2 解决方案 520 13.4.3 工作原理 521 13.5 向集成测试注入测试夹具 526 13.5.1 问题 526 13.5.2 解决方案 526 13.5.3 工作原理 527 13.6...
1.1.2. 在Tomcat 服务器上运行示例.......................................................................................................................... 15 1.1.3. 运行测试..............................