1

我有一个MarshalByReferenceObject,其方法是通过 .net 远程处理调用的。

public class MyServer : MarshalByReferenceObject
{
    public void DoSomething();
}

System.Runtime.Remoting.RemotingConfiguration.RegisterWellKnownServiceType(
            typeof(MyServer), "serverUrl", System.Runtime.Remoting.WellKnownObjectMode.SingleCall);

客户端像这样调用服务器:

var server = Activator.GetObject(typeof(MyServer), "serverUrl");
server.DoSomething();

现在出于调试目的,当客户端调用 DoSomething() 方法时,我想记录实际调用者是谁。

如何从我的 server.DoSomething() 函数中识别调用方法?或者从我的服务器构造函数中,它由 Activator.GetObject 调用?

理想情况下,我想要整个堆栈跟踪:哪个客户端方法调用服务器,哪个父方法调用该客户端方法,等等。但我会接受某种来电显示。我控制着客户,所以也许我可以以某种方式给他们起名字?string callerId接口规范已经非常固定,所以我想避免为每个方法添加一个多余的参数。

本地堆栈跟踪当然只识别System.Runtime.Remoting方法,而不是实际的远程调用者。


服务器端的示例堆栈跟踪:

    at MyServer.MyServer(), line 123
    at System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck)
    at System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache)
    at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipVisibilityChecks, Boolean skipCheckThis, Boolean fillCache)
    at System.Activator.CreateInstance(Type type, Boolean nonPublic)
    [...] 
    at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)

这显然不能帮助我识别来自客户端的调用方法。

4

1 回答 1

2

如果您可以选择稍微调整客户端和服务器的工作方式,则可以将参数传递给您的协议类 ( MyServer) 构造函数。

在服务器端,您可以使用它RemotingConfiguration.RegisterActivatedServiceType来注册您的协议类。

在客户端,您可以调用RemotingConfiguration.RegisterActivatedClientType以注册您希望在服务器上创建协议类的实例。然后您可以创建一个新实例并将您喜欢的任何客户端标识参数传递给构造函数(以正常方式,不带Activator.GetObject),该对象将在服务器上自动创建并在本地代理。

协议类

using System;

public class MyServer : MarshalByRefObject
{
    Guid clientID;

    public MyServer(Guid clientID)
    {
        this.clientID = clientID;
    }

    public void DoSomething()
    {
        Console.WriteLine("Logged operation from client {0}.", this.clientID);
    }
}

服务器

using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;

class Server
{
    static void Main(string[] args)
    {
        ChannelServices.RegisterChannel(new TcpServerChannel(1234), false);
        RemotingConfiguration.ApplicationName = "Test";
        RemotingConfiguration.RegisterActivatedServiceType(typeof(MyServer));
        Console.WriteLine("Server listening ...");
        Console.ReadLine();
    }
}

客户

using System;
using System.Runtime.Remoting;

class Client
{
    static void Main(string[] args)
    {
        RemotingConfiguration.RegisterActivatedClientType(typeof(MyServer),
                                      "tcp://localhost:1234/Test");
        var id = Guid.NewGuid();
        Console.WriteLine("Creating object with id {0}.", id);
        var obj = new MyServer(id);
        obj.DoSomething();
    }
}
于 2015-03-09T00:33:54.403 回答