3

这是java中的示例代码。

共享接口:

import java.rmi.Remote;
import java.rmi.RemoteException;

public interface Compute extends Remote {
  public Object executeTask(Task t) throws RemoteException;
}

任务(这将作为参数传递):

import java.io.Serializable;

public interface Task extends Serializable {
  public Object execute();
}

服务器:

import java.rmi.Naming;
import java.rmi.RMISecurityManager;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

public class ComputeEngine extends UnicastRemoteObject implements Compute {

  public ComputeEngine() throws RemoteException {
    super();
  }

  public Object executeTask(Task t) {
    return t.execute();
  }

  public static void main(String[] args) {
    setRmiCodebase();
    System.setSecurityManager(new RMISecurityManager());
    try {
      Compute engine = new ComputeEngine();
      Naming.rebind("//localhost:1099/Compute", engine);
      System.out.println("ComputeEngine started.");
    } catch (Exception ex) {
      ex.printStackTrace();
    }
  }

  private static void setRmiCodebase() {
    String codebase = System.getProperty("java.rmi.server.codebase");
    if (codebase != null)
      return;
    // set codebase based on location of this clsas (is it in jar or filesistem?)
  }

}

客户:

import java.math.BigDecimal;
/**
* Calculates Pi to arbitrary number of digits:
*/
public class Pi implements Task {

  public Pi(int digits) {
    this.digits = digits;
  }

  public Object execute() {
    return computePi(digits);
  }

  public static BigDecimal computePi(int digits) {
    // compute Pi
  }

}

客户主要:

import java.math.BigDecimal;
import java.rmi.Naming;
import java.rmi.RMISecurityManager;

public class ComputePi {

  public static void main(String[] args) {
    setRmiCodebase();
    System.setSecurityManager(new RMISecurityManager());
    try {
      Compute comp = (Compute)Naming.lookup("//localhost:1099/Compute");
      Pi task = new Pi(100);
      BigDecimal pi = (BigDecimal)comp.executeTask(task);
      System.out.println(pi);
    } catch (Exception ex) {
      ex.printStackTrace();
    }
  }

  private static void setRmiCodebase() {
    String codebase = System.getProperty("java.rmi.server.codebase");
    if (codebase != null)
      return;
    // set codebase based on location of this clsas (is it in jar or filesistem?)
  }
}

如您所见,来自客户端的代码(不仅仅是数据)被传输到服务器并在那里执行并返回计算结果。服务器不知道该类的Pi存在,它只知道Task接口。

我需要这样的东西才能在 .net 环境中工作(如果很重要,请使用 C#)。WCF 会很好,但我正在寻找最直接的解决方案,所以 WCF 不是强制性的。我什至不确定使用什么关键字来谷歌文档或解决方案。

任何帮助将不胜感激。

4

5 回答 5

2

Afaik .NET 不支持开箱即用 - 您可以进行远程处理,但这不会(按原样)让您从服务器上的客户端运行代码。我认为您必须实现一些东西,将包含您要执行的代码的 dll 传输到服务器,然后可能将该 dll 加载到单独的 AppDomain 中(因为除非您将它们加载到单独的 AppDomain 中,否则您无法卸载 dll) ,然后有办法指定要运行的类。

于 2012-05-31T12:37:51.087 回答
1

您想要的是 .NET Remoting。 这里是文章的链接,展示了如何从 RMI 迁移到 .NET Remoting。

但根据这篇 MSDN 文章,这是一项遗留技术,您应该使用 WCF。

编辑:

您不能“就那样”使用 WCF 获得 .NET Remoting 功能。

在这里,您可以阅读有关从 .NET Remoting 移植到 WCF 的讨论。但是如果你根本不知道 WCF 你应该从这里开始。而且你可能不会很快得到你的结果:)。

于 2012-05-31T12:29:05.147 回答
1

.NET 本身不支持在另一台计算机上执行“发送代码”。通常,必要的代码会在客户端调用之前编译为程序集并预安装在服务器上。远程处理和 WCF 都是如此。您可能会遇到双向远程处理情况,即服务器通过 WCF 回调客户端上的方法,但我怀疑这不是您想要的。我知道在服务器上真正运行动态代码的唯一方法是生成动态代码,将其作为字符串发送到服务器,然后让服务器将其编译为内存中的程序集,然后执行它。如果您有兴趣这样做,请查看我对类似问题的回答:

自动激活属性?

但是,在大多数情况下,这并不是我所建议的。我建议您首先重新考虑您的设计,看看是否有任何方法可以以典型的“.NET 方式”完成您需要的工作。

于 2012-05-31T13:08:09.947 回答
1

这个 MSDN 页面或多或少有你描述的这个确切的用例。你只需要修改ServiceContract

http://msdn.microsoft.com/en-us/library/system.servicemodel.netnamedpipebinding.aspx

您可能只需要修改这部分:

 [ServiceContract(Namespace = "http://UE.Samples")]
    public interface ICalculator
    {
        [OperationContract]
        double Add(double n1, double n2);
    }

    // Service class which implements the service contract.
    public class CalculatorService : ICalculator
    {
        public double Add(double n1, double n2)
        {
            return n1 + n2;
        }

而不是标量值,而是将您的 executeTask 方法与您自己的类的参数放在那里。

于 2012-05-31T13:11:05.660 回答
0

我不相信.NET 有用于将可执行代码从客户端传输到服务器的内置解决方案。假设安全约束允许,您可以考虑发送可解释的代码,例如 Python 或 JavaScript,它们可以分别通过IronPythonIronJS在服务器端执行。如果需要 C#(并且您仍然可以访问源代码),请发送源代码并在服务器端编译(通过 Roslyn 或 Mono 的评估器)。

于 2012-05-31T12:54:49.143 回答