Remoting CallContext 实现客户端识别
最近整理一个Remoting项目, 需要识别客户端。最先想到的是WCF的MessageHeader,WebService的SoapHeader,抑或是通过消息拦截能够加入额外的信息。 调查了下发现 Remoting 实现消息拦截还比较麻烦(需要实现RealProxy等,详细看这里:http://www.cnblogs.com/idior/articles/872380.html)。 好在 Remoting 里还有个东东叫 CallContext 的东东可以封送额外的信息,调用上下文在应用程序域边界被克隆,其数据槽不在其他逻辑线程上的调用上下文之间共享。 当然放入 CallContext 的数据需要实现 ILogicalThreadAffinative 接口。
Identity.cs
using System;
using System.Runtime.Remoting.Messaging;
namespace RemotingCommLib
{
[Serializable]
public class Identity : ILogicalThreadAffinative
{
// 客户端标识
public string ClientID { get; set; }
public string ExtensionData { get; set; }
}
}
服务端实现
using System;
using RemotingCommLib;
using System.Runtime.Remoting.Messaging;
namespace RemotingServiceHost
{
public class Service : MarshalByRefObject, IService
{
public string GetServerTime()
{
Identity identity = CallContext.GetData("identity") as Identity;
Console.WriteLine("Client[{0}] access.", identity.ClientID);
return string.Format("Get message from server at {0:HH:mm:ss}", DateTime.Now);
}
}
}
客户端调用
using System;
using System.Runtime.Remoting;
using RemotingCommLib;
using System.Runtime.Remoting.Messaging;
using System.Threading;
namespace RemotingClient
{
class Program
{
static void Main(string[] args)
{
string config = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;
RemotingConfiguration.Configure(config, false);
string url = RemotingConfiguration.GetRegisteredWellKnownClientTypes()[0].ObjectUrl;
IService client = (IService)Activator.GetObject(typeof(IService), url);
Identity identity = new Identity();
identity.ClientID = Guid.NewGuid().ToString();
CallContext.SetData("identity", identity);
string reply = client.GetServerTime();
Console.WriteLine("Client {0}:{1}", identity.ClientID, reply);
Thread.Sleep(1000);
IService client1 = (IService)Activator.GetObject(typeof(IService), url);
string reply1 = client1.GetServerTime();
Console.WriteLine("Client {0}:{1}", identity.ClientID, reply1);
Console.Read();
}
}
}
启动两个客户端调用:
服务端通过 CallContext.GetData 取到了客户端的标识ID。通过这种方法,还可以实现用户名密码的验证。