.NET Remoting:如何从远程对象访问服务器应用程序对象?

发布于 2024-07-11 21:35:21 字数 1013 浏览 1 评论 0原文

我正在编写一个 Windows 服务应用程序,将通过 .NET Remoting 访问该应用程序。 问题是我无法弄清楚如何从远程类访问服务对象。

例如,我有一个处理程序类:

class Service_console_handler
   {
    public int something_more = 20;

    //some code...

            TcpChannel serverChannel = new TcpChannel(9090);
            ChannelServices.RegisterChannel(serverChannel);
            RemotingConfiguration.RegisterWellKnownServiceType(
                        typeof(RemoteObject), "RemoteObject.rem", 
                        WellKnownObjectMode.Singleton);

    //from here on RemoteObject is accessible by clients.
    //some more code doing something and preparing the data...
   }

我有一个远程类:

public class RemoteObject : MarshalByRefObject
{
    private int something = 10;

    public int Get_something()
    {
        return something;
    }
}

客户端可以毫无问题地访问 RemoteObect 中的数据。 但是我如何访问 Service_console_handler 对象(即从 something_more 检索有用的信息)?

抱歉提出了愚蠢的问题,并提前致谢。

I'm writing a windows service application, which will be accessed through .NET Remoting.
The problem is I can't figure out how to access service objects from remotable class.

For example, I've a handler class:

class Service_console_handler
   {
    public int something_more = 20;

    //some code...

            TcpChannel serverChannel = new TcpChannel(9090);
            ChannelServices.RegisterChannel(serverChannel);
            RemotingConfiguration.RegisterWellKnownServiceType(
                        typeof(RemoteObject), "RemoteObject.rem", 
                        WellKnownObjectMode.Singleton);

    //from here on RemoteObject is accessible by clients.
    //some more code doing something and preparing the data...
   }

And I've a remotable class:

public class RemoteObject : MarshalByRefObject
{
    private int something = 10;

    public int Get_something()
    {
        return something;
    }
}

Clients can access data in RemoteObect with no problem. But how can I access Service_console_handler object (i.e. to retrieve useful info from something_more)?

Sorry for dumb questions and thanks in advance.

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

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

发布评论

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

评论(2

烟燃烟灭 2024-07-18 21:35:21

您想要的是通过 RemoteObject 实例以某种方式访问​​ ServiceConsoleHandler 实例,该实例对客户端可见。

为此,您需要考虑两件事:(1) 控制 RemoteObject 实例的对象构造并使其可访问;(2) 修改 ServiceConsoleHandler 以便它可以远程访问。

(1)

如果不需要考虑远程处理,如何在 ServiceConsoleHandler 中构造 RemoteObject 实例?

我想你会做这样的事情:

class ServiceConsoleHandler
{
   …
   RemoteObject remoteObject = new RemoteObject();
   // now assume that you also already have
   // modified the RemoteObject class so it can hold
   // a reference to your server:
   remoteObject.Server = this;
   …
}

如果你能让客户端可以访问这个对象,那就太好了。 您可以使用 RemotingServices.Marshal 而不是 RemotingConfiguration.RegisterWellKnownServiceType 来执行此操作:

class ServiceConsoleHandler
{
     …
     TcpServerChannel channel = new TcpServerChannel(9090);
     ChannelServices.RegisterChannel(channel, true);
     RemoteObject remoteObject = new RemoteObject();
     remoteObject.Server = this;
     RemotingServices.Marshal(remoteObject, "RemoteObject.rem");
     …
}

(2)

如果您现在执行代码并在客户端代码中访问 remoteObject.Server,您将得到一些远程异常,因为 ServiceConsoleHandler 类无法远程访问。 因此,您需要添加 [Serializable] 属性:

[Serializable]
class ServiceConsoleHandler
{ … }

原因:应远程访问的类型需要编组为某种特殊的可传输表示形式。 这样它们就可以通过 TCP 端口被挤压并通过 TCP 协议进行传输。 基本数据类型可以由框架封送,因此您不需要考虑它们。 对于自定义类型,您需要说明如何执行此操作。 实现此目的的一种方法是从 MarshalByRefObject 进行子类化。 这正是您已经使用 RemoteObject 所做的事情。 另一种方法是将自定义类标记为 [Serialized],如上所示。

就是这样。 现在您应该能够在客户端代码中访问服务器的字段。 请注意,您不需要现有代码来激活对象:

        TcpClientChannel channel = new TcpClientChannel();
        ChannelServices.RegisterChannel(channel, true);

        RemoteObject remoteObject = (RemoteObject)Activator.GetObject(
            typeof(RemoteObject), "tcp://localhost:9090/RemoteObject.rem");

        Console.WriteLine(remoteObject.Server.SomethingMore);

对我来说,.NET 远程处理充满了有趣的惊喜和不眠之夜。 为了解决这个问题,请让自己熟悉远程概念(从我的角度来看,这些概念的记录很少)。 深入研究序列化概念(MarshalByRefObject[Serialized])。 如果您想用它编写生产代码,请考虑处理远程异常的好方法。 还要考虑多线程。 可能有多个客户端同时使用该远程对象。

玩得开心!

What you want is somehow to access the instance of ServiceConsoleHandler via a RemoteObject instance, which is visible for the client.

For this you need to consider two things: (1) Get control over the object construction of the RemoteObject instance and make it accessible and (2) modify ServiceConsoleHandler so it can be accessed remotely.

(1)

How would you construct a RemoteObject instance in ServiceConsoleHandler, if you don’t need to consider remoting?

I guess you would do something like this:

class ServiceConsoleHandler
{
   …
   RemoteObject remoteObject = new RemoteObject();
   // now assume that you also already have
   // modified the RemoteObject class so it can hold
   // a reference to your server:
   remoteObject.Server = this;
   …
}

It would be nice if you could make this object accessible for the client. You can do this by using RemotingServices.Marshal instead of RemotingConfiguration.RegisterWellKnownServiceType:

class ServiceConsoleHandler
{
     …
     TcpServerChannel channel = new TcpServerChannel(9090);
     ChannelServices.RegisterChannel(channel, true);
     RemoteObject remoteObject = new RemoteObject();
     remoteObject.Server = this;
     RemotingServices.Marshal(remoteObject, "RemoteObject.rem");
     …
}

(2)

If you execute the code right now and access the remoteObject.Server in the client code you would get some remoting exception, because the class ServiceConsoleHandler cannot be accessed remotely. Therefore you need the add the [Serializable] attribute:

[Serializable]
class ServiceConsoleHandler
{ … }

Reason: Types which should be accessed remotely, need to be marshaled to some special transferrable representation. This way they can be squeezed through the TCP port and transferred via the TCP protocol. Basic data types can by marshaled by the framework, so you don't need to think about them. For custom types you will need to state, how to do this. One way to do this is by subclassing from MarshalByRefObject. That’s exactly what you have already done with RemoteObject. Another way is to mark your custom classes as [Serializable] as shown above.

That’s it. Now you should be able to access the server’s field in the client code. Note that you don’t need your existing code for object activation:

        TcpClientChannel channel = new TcpClientChannel();
        ChannelServices.RegisterChannel(channel, true);

        RemoteObject remoteObject = (RemoteObject)Activator.GetObject(
            typeof(RemoteObject), "tcp://localhost:9090/RemoteObject.rem");

        Console.WriteLine(remoteObject.Server.SomethingMore);

For me .NET remoting is full of funny surprises and sleepless nights. To counter this, make yourself familiar with the remoting concepts (which are from my point of view poorly documented). Dig into the serialization concept (MarshalByRefObject vs. [Serializable]). If you want to make a production code out of it, think a very good ways to handle remoting exceptions. Also consider multithreading. There could be more than one client using this remote object at once.

Have fun!

那一片橙海, 2024-07-18 21:35:21

谢谢你! 我非常感谢您回答的彻底性和清晰度。

最奇怪的是我什至不知道你可以发布对象实例。 我研究了大约十几个简单的教程,建议将 RemotingConfiguration.RegisterWellKnownServiceType 作为进行远程处理的唯一方法。 愚蠢的我。

现在远程处理对我来说看起来更有用。 我刚刚编写了一个快速测试应用程序并且它有效。 再次感谢。

Thank you! I very much appreciate thoroughness and clarity of you answer.

Most bizzare thing is that I didn't even know that you can publish object instance. About a dozen simple tutorials I studied proposed RemotingConfiguration.RegisterWellKnownServiceType as only method to do remoting. Stupid me.

Now remoting looks much more useful to me. I just wrote a quick test application and it worked. Thanks again.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文