在.NET远程处理调用期间标识客户端

时间:2009-02-09 10:31:23

标签: .net multithreading remoting

鉴于此MarshalByRef类:

public class MyRemotedClass : MarshalByRef
{
  public void DoThis()
  {
     ...
  }
  public void DoThat()
  {
     ...
  }
}

客户端代码:

MyRemotedClass m = GetSomehowMyRemotedClass();
m.DoThis();
m.DoThat();

我可以让几个客户同时做同样的事情。 我想区分客户。 如何在远程访问的方法中识别执行远程调用的人员? 例如,我可以记录谁做了什么。 (实际上,我不需要追溯真正的客户信息,我只是希望能够对客户进行分组调度。)

[已编辑添加更多背景信息]

我需要处理大量代码,包括属性。因此,不能选择扩展输入参数列表。

1 个答案:

答案 0 :(得分:16)

您可以做的一件事是通过实施IServerChannelSinkProvider按IP地址识别客户。

将此类添加到远程主机项目中:

ClientIPServerSinkProvider.cs

using System;
using System.Collections;
using System.IO;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Channels;
using System.Threading;
using System.Net;

namespace MyRemotingEnvironment
{
    public class ClientIPServerSinkProvider : 
        IServerChannelSinkProvider
    {
        private IServerChannelSinkProvider _nextProvider = null;

        public ClientIPServerSinkProvider()
        {
        }

        public ClientIPServerSinkProvider(
            IDictionary properties, 
            ICollection providerData)
        {
        }

        public IServerChannelSinkProvider Next
        {
            get { return _nextProvider; }
            set { _nextProvider = value; }
        }

        public IServerChannelSink CreateSink(IChannelReceiver channel)
        {
            IServerChannelSink nextSink = null;

            if (_nextProvider != null)
            {
                nextSink = _nextProvider.CreateSink(channel);
            }
            return new ClientIPServerSink(nextSink);
        }

        public void GetChannelData(IChannelDataStore channelData)
        {
        }
    }



    public class ClientIPServerSink : 
        BaseChannelObjectWithProperties, 
        IServerChannelSink, 
        IChannelSinkBase
    {

        private IServerChannelSink _nextSink;

        public ClientIPServerSink(IServerChannelSink next)
        {
            _nextSink = next;
        }

        public IServerChannelSink NextChannelSink
        {
            get { return _nextSink; }
            set { _nextSink = value; }
        }

        public void AsyncProcessResponse(
            IServerResponseChannelSinkStack sinkStack, 
            Object state, 
            IMessage message, 
            ITransportHeaders headers, 
            Stream stream)
        {
            IPAddress ip = headers[CommonTransportKeys.IPAddress] as IPAddress;
            CallContext.SetData("ClientIPAddress", ip);
            sinkStack.AsyncProcessResponse(message, headers, stream);
        }

        public Stream GetResponseStream(
            IServerResponseChannelSinkStack sinkStack, 
            Object state, 
            IMessage message, 
            ITransportHeaders headers)
        {

            return null;

        }


        public ServerProcessing ProcessMessage(
            IServerChannelSinkStack sinkStack, 
            IMessage requestMsg, 
            ITransportHeaders requestHeaders, 
            Stream requestStream, 
            out IMessage responseMsg, 
            out ITransportHeaders responseHeaders, 
            out Stream responseStream)
        {
            if (_nextSink != null)
            {
                IPAddress ip = 
                    requestHeaders[CommonTransportKeys.IPAddress] as IPAddress;
                CallContext.SetData("ClientIPAddress", ip);
                ServerProcessing spres = _nextSink.ProcessMessage(
                    sinkStack, 
                    requestMsg, 
                    requestHeaders, 
                    requestStream, 
                    out responseMsg, 
                    out responseHeaders, 
                    out responseStream);
                return spres;
            }
            else
            {
                responseMsg = null;
                responseHeaders = null;
                responseStream = null;
                return new ServerProcessing();
            }
        }


    }
}

然后当您启动远程主机时,执行以下操作:

BinaryServerFormatterSinkProvider bp = new BinaryServerFormatterSinkProvider();
ClientIPServerSinkProvider csp = new ClientIPServerSinkProvider();
csp.Next = bp;
Hashtable ht = new Hashtable();
ht.Add("port", "1234"); // Your remoting port number
TcpChannel channel = new TcpChannel(ht, null, csp);
ChannelServices.RegisterChannel(channel, false);

RemotingConfiguration.RegisterWellKnownServiceType(
    typeof(MyRemotedClass), 
    "MyRemotedClass.rem", 
    WellKnownObjectMode.SingleCall);

在您的方法调用中,您可以通过执行以下操作来访问客户端的IP地址:

public class MyRemotedClass : MarshalByref
{
    public void DoThis()
    {
        string clientIP = CallContext.GetData("ClientIPAddress").ToString();
    }
}