科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件C#中的远程执行和分布式计算

C#中的远程执行和分布式计算

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

远程执行是C#中一种使开发人员能够使用远程对象的基础架构。远程对象是一种位于调用者应用域之外的对象

作者:刘彦青 来源:Yesky 2007年11月14日

关键字:

  • 评论
  • 分享微博
  • 分享邮件
运行例子程序

  这个例子是用C# for .NET Beta 2编写的,并在C# for .NET Beta 2中通过了测试。

  为了使用任务服务器,我们必须以下面的顺序对程序进行编译:

csc /target:library /out:ITask.dll ITask.cs
csc /target:library /out:TaskRunner.dll TaskRunner.cs

csc /r:ITask.dll /r:TaskRunner.dll TaskServer.cs

csc /r:ITask.dll /r:TaskRunner.dll TaskClient.cs

   上面的顺序非常重要,因为TaskServer和TaskClient类要用到TaskRunner和ITask库。

  要运行这个例子程序,首先启动服务器代码,并等待出现下面的提示:

[i] Task Server Started, press to exit?

  然后就可以运行客户端程序了。

  在TaskClient类中有一个实现ITask界面而且能够可串行化的类,该任务将求出二个数的积,并返回一个int类型的对象。我建议读者创建自己的任务,并试着在任务服务器上运行它,这将使你亲身体会到这种分布式计算的巨大威力。它可以使客户端软件开发人员充分利用任务服务器上丰富的资源完成复杂的、需要大量资源的任务。

  我们可以利用任务服务器完成诸如数字处理、压缩、加密、排序等各种操作。

  正面是本文中例子所涉及的源代码,及其简单的注解,供有兴趣的读者参考:

// ITask.cs

// 用户可以使用该界面来创建自己的任务,它完成下面的二种操作:
// ·服务器可以通过调用方法Run()来运行建立的任务。
// ·客户端可以保证任务从方法Run()中启动。
// 其中还有一个Identify()方法,服务器用它显示一些有关任务的信息。
// 该界面被编译为同一个名字空间下的单独的库文件,使得任务服务器的管理员能够将该界面作为所有能够在//他的任务服务器上运行的任务的契约进行分发。
// 客户端将继承该类,创建自己的任务对象,提交给服务器运行。

namespace TaskServer {

 // 必须将它定义为一个界面
 public interface ITask {

  object Run();

  string Identify();
 }
}
// TaskRunner.cs

// 该对象用来运行由客户端提交的任务,提交的任务将在服务器的应用域执行。
// TaskRunner对象以引用的方式传递给客户端,无需对它进行串行化
// TaskRunner接受所有实现ITask界面的任务,它需要二个参数:Run()和Identify()。

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

namespace TaskServer {

public class TaskRunner : MarshalByRefObject {

ITask remoteTaskObject;

public TaskRunner() {
Console.WriteLine("\n[i] TaskRunner activated");
}

public string LoadTask(ITask task) {

Console.WriteLine("\n[i] Loading new task...");

if(task == null) {
Console.WriteLine("[e] Task reference is NULL. Task not Loaded.");
return "[e] Task not loaded.";
}

remoteTaskObject = task;
Console.WriteLine("[i] Task has been loaded.");
Console.WriteLine("[i] Task ID: " + remoteTaskObject.Identify() + "\n");
return "[i] Task loaded. Welcome to the All Powerful TaskServer.";
}

public object RunTask() {

Console.WriteLine("\n[i] Running the task...");

object result = remoteTaskObject.Run();

Console.WriteLine("[i] Task finished.");

return result;
}
}
}
// TaskServerEngine.cs

// 这个类用来启动任务服务器应用程序。它建立C#远程执行的后端,加载通道,注册TaskRunner对象,然后让 //远程执行机制的后端监测TCP通道上的连接请求

using System;
using System.IO;

// 下面的库用于向远程执行机制注册我们的对象
using System.Runtime.Remoting;
// 下面的库用于向通道服务注册我们的TCP通道设备
using System.Runtime.Remoting.Channels;
// 该库提供了用来与远程应用域(客户端)通讯所需要的TCP通道
using System.Runtime.Remoting.Channels.Tcp;

namespace TaskServer {

public class TaskServerEngine {

// 我们只需要一个方法,它可以是静态的,因为我们不需要建立这个类的实例,该方法的作用仅仅是 //创建并创始化TaskServerEngine。
public static void Main() {

// 向用户表明我们正在启动服务器类
Console.WriteLine("The All Powerful Task Server!");
Console.WriteLine("....\"Your Task is My Command\"....");
Console.WriteLine("\n[i] Starting Task Server...");

try {
// 创建TCP通道
Console.WriteLine("[i] -- Creating TCP channel");
TcpChannel chan = new TcpChannel(8085);

// 向.NET的远程服务注册新创建的TcpChannel,使客户端可以使用这一服务
Console.WriteLine("[i] -- Registering TCP channel");
ChannelServices.RegisterChannel(chan);

//向远程机制的后端注册TaskRunner对象,RegisterWellKnownServiceType方法将完成这一 //操作,并接收下面的参数:
// *内容为TaskRunner对象映象的类型对象
// * 向客户公布的服务名字
// * 对象的模式:Singleton意味着所有客户端请求共享一个对象服务;SingleCall意味着 // 每个客户端请求使用一个新的对象服务。
Console.WriteLine("[i] -- Registering the TaskRunner object");
Type theType = new TaskRunner().GetType();
RemotingConfiguration.RegisterWellKnownServiceType(theType, "TaskServer", WellKnownObjectMode.Singleton);


Console.WriteLine("[i] Task Server started, press to exit...");
Console.ReadLine();
} catch (Exception e) {
Console.WriteLine("[!] An error occured while initialising the TaskServerEngine.");
Console.WriteLine(e);
}
}
}
}
// TaskClient.cs
// 这是一个客户端应用域,客户端的任务是建立一个任务对象,并将它提交给任务服务器
using System;

// 建立与任务服务器的连接所必需的库文件
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;

using TaskServer;

namespace HappyClientWithTask {

[Serializable()]

// 下面是我们创建的任务
class ClientTask : ITask {

private int num1, num2;
private int result;

public ClientTask(int num1, int num2) {
this.num1 = num1;
this.num2 = num2;
}

public object Run() {
result = num1 * num2;
return (object)result;
}

public string Identify() {
return("I am a multiplication task.");
}
}

public class Client {

public static void Main() {

Console.WriteLine("\nWelcome to the humble, lowly client Application Domain.\n");

ClientTask clientTask = new ClientTask(100,100);

try {
Console.WriteLine("[i] Connecting to TaskServer...");
Console.WriteLine("[i] - Opening TCP Channel");
TcpChannel chan = new TcpChannel();
Console.WriteLine("[i] - Registering the channel");
ChannelServices.RegisterChannel(chan);
Console.WriteLine("[i] Connected to TaskServer");

// 从TaskServer中获取TaskRunner对象的引用
// Activator类中的GetObject方法需要二个参数:
// * 对象类型
// * 对象的URI位置
Console.WriteLine("[i] Getting a reference to the TaskRunner Object");
TaskRunner taskRunner = (TaskRunner)Activator.GetObject(typeof(TaskServer.TaskRunner),
"tcp://localhost:8085/TaskServer");

if(taskRunner == null) {
Console.WriteLine("[e] Could not locate server.");
Console.WriteLine("[i] Exiting...");
return;
}

Console.WriteLine("[i] We have an object reference!");

// 下面我们将把任务对象传递给任务服务器
Console.WriteLine("\n[i] Submitting our task to the server...");
string response = taskRunner.LoadTask(clientTask);

Console.WriteLine("[i] Server says: " + response);

Console.WriteLine("\n[i] Running the task and awaiting feedback...");
object result = taskRunner.RunTask();

Console.WriteLine("[aaa-uuuum] The Great and Powerful TaskServer Says: " + (int)result);
} catch (Exception e) {

Console.WriteLine("[e] An exception occurred.");
Console.WriteLine(e);
}

}
}
}

查看本文来源

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章