Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/299.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
发送要在服务器上执行的C#类Java RMI代码_C#_Java_Wcf_Rmi - Fatal编程技术网

发送要在服务器上执行的C#类Java RMI代码

发送要在服务器上执行的C#类Java RMI代码,c#,java,wcf,rmi,C#,Java,Wcf,Rmi,这是java中的示例代码 共享接口: import java.rmi.Remote; import java.rmi.RemoteException; public interface Compute extends Remote { public Object executeTask(Task t) throws RemoteException; } import java.rmi.Naming; import java.rmi.RMISecurityManager; import j

这是java中的示例代码

共享接口:

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

public interface Compute extends Remote {
  public Object executeTask(Task t) throws RemoteException;
}
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.rmi.Remote;
import java.rmi.RemoteException;

public interface Compute extends Remote {
  public Object executeTask(Task t) throws RemoteException;
}
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.rmi.Remote;
import java.rmi.RemoteException;

public interface Compute extends Remote {
  public Object executeTask(Task t) throws RemoteException;
}
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不是强制性的。我甚至不知道用什么关键字来谷歌文档或解决这个问题


任何帮助都将不胜感激

您需要的是.NET远程处理。 链接到介绍如何从RMI迁移到.NET远程处理的文章

但根据这项传统技术,您应该使用WCF

编辑:

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

public interface Compute extends Remote {
  public Object executeTask(Task t) throws RemoteException;
}
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
  }

}
您不能“像那样”使用WCF获得.NET远程处理功能

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

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

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

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


然而,在大多数情况下,这并不完全是我的建议。我建议您重新考虑您的设计,首先,看看是否有任何方法可以以典型的“.NET”方式实现您所需的功能。

此MSDN页面或多或少与您描述的用例相同。您只需要修改ServiceContract

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

 [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方法放在那里,而不是标量值。

谢谢。由于.net远程处理是遗留的,您是否有我如何使用WCF实现相同结果的链接?我阅读文档没有问题,但我想知道在我花费数小时/数天的时间使其工作之前,是否可以将代码从客户端发送到服务器以执行。我知道WCF的基本概念,但我不知道它是否支持我所需要的(其他答案表明这是不可能的)。@del-boy:好的。现在我有一个问题。您不在乎在两个应用程序中使用相同的引用,对吗?你并不需要这个确切的功能(共享对象)。您只希望客户机使用接口(而不是被迫在所有实现中引用dll),而不关心服务器端的情况。对吗?你们是对的,我不需要相同的引用,我只想让服务器在我作为参数发送实例的类上执行方法。但你们需要发送任何实例吗?如果只是计算,你不能简单地告诉你的服务器进行计算并返回结果?毕竟RMI不这样做(发送实例)。它只是通过远程调用对象方法来模拟它。我错了吗?你确定吗?在回答一个问题之前,我试着按照本教程进行操作:并用类的实例替换标量值,但我得到了CommunicationException和实现DataContractResolver的建议,但据我所知,data contract无法发送代码,所以我没有这样做。NetNamedPipeBinding是否提供此功能?你能提供这方面的工作实例吗?谢谢。你可以在合同上使用特定的类,而不是接口类型,因为序列化是二进制的。这就是我所知道的。发送可解释代码是另一种有缺陷的方法,所以我不想考虑它。我有一个想法,发送表达式树并在服务器上编译它以进行委托,但如果这不起作用,我会考虑这个问题。谢谢