在 .NET 远程调用期间识别客户端

发布于 2024-07-13 12:58:11 字数 504 浏览 9 评论 0原文

给定这个 MarshalByRef 类:

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

客户端代码:

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

我可以让多个客户端同时执行相同的操作。 我想区分客户。 如何在远程访问的方法内部识别远程调用由谁执行? 例如,我可以记录谁做了什么。 (实际上,我不需要追溯真实的客户端信息,我只是希望能够对客户端的调用进行分组。)

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

我有大量的代码需要涵盖,包括属性。 因此扩展输入参数列表不是一个选项。

Given this MarshalByRef class:

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

Client side code:

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

I can have several clients doing the same thing at a the same time.
I would like to distinct the clients. How can I identify inside the remotely accessed methods, by whom the remoting invocation is executed?
For example, I could log who did what. (Actually, I do not need to trace back the true client info, I just want to be able to group invocations by clients.)

[Edited to add more background info]

I have enormous amount of code to cover, including properties. Therefore extending the input parameter list is not an option.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

与风相奔跑 2024-07-20 12:58:12

您可以做的事情之一是通过实现 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();
    }
}

One of the things you can do is identify a client by IP address by implementing an IServerChannelSinkProvider.

Add this class to your remoting host project:

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();
            }
        }


    }
}

Then when you start your remoting host do something like the following:

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);

In your method calls you can access the IP address of the client by doing:

public class MyRemotedClass : MarshalByref
{
    public void DoThis()
    {
        string clientIP = CallContext.GetData("ClientIPAddress").ToString();
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文