分布式编程
我采用的是Remoting来作为通道,但是服务器启动之后,客户端要连接的时候,提示,找不到什么程序集,上网找了一下资料,说是在用之前,要用 Microsoft .NET Configuration这个注册不知道有谁做过这方便,给个提示 --------------------编程问答-------------------- 填加引用
客户机装.net了吗... --------------------编程问答-------------------- TaskRunner taskRunner = (TaskRunner)Activator.GetObject(typeof(TaskServer.TaskRunner),
"tcp://localhost:8085/TaskServer");
tcp://localhost:8085/TaskServer 主要是这个,访问不了,需要注册,怎么注册?(是一个DLL文件) --------------------编程问答-------------------- 在客户程序里你是不是没添加引用“TaskServer.TaskRunner” --------------------编程问答-------------------- 程序生成的时候都没错,就是运行的时候提示错,这个不是引用的问题,是服务器必须注册,但是我不知道怎么注册 --------------------编程问答-------------------- RemotingConfiguration.Configure(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile); --------------------编程问答--------------------
guoyichao 能否把注册的流程说的具体一点
例如:第一步....
第二步....
谢谢了 --------------------编程问答-------------------- TaskRunner taskRunner = (TaskRunner)Activator.GetObject(typeof(TaskServer.TaskRunner),
"tcp://localhost:8085/TaskServer");
tcp://localhost:8085/TaskServer 主要是这个,访问不了,需要注册,怎么注册?(是一个DLL文件)
你在服务端,需要注册TaskServer这个类
TcpServerChannel channel = new TcpServerChannel(8888);
ChannelServices.RegisterChannel(channel, false);
RemotingConfiguration.RegisterWellKnownServiceType(typeof(TaskServer), "TaskServer", WellKnownObjectMode.SingleCall);
----------
三易通软件(服装进销存,服装进销存软件,服装进销存管理软件,服装进销存管理系统,服装店管理软件,服装店管理系统,服装销售管理软件,服装销售管理系统,服装零售管理软件,服装零售管理系统,服装店软件,服装店收银软件):http://www.3etsoft.cn --------------------编程问答-------------------- 这个通道也注册过了,代码如下:
// 创建TCP通道
Console.WriteLine("[i] -- 创建TCP通道");
TcpChannel chan = new TcpChannel(8085);
// 向.NET的远程服务注册新创建的TcpChannel,使客户端可以使用这一服务
Console.WriteLine("[i] -- 注册TCP通道");
ChannelServices.RegisterChannel(chan, false);
//向远程机制的后端注册TaskRunner对象,RegisterWellKnownServiceType方法将完成这一 //操作,并接收下面的参数:
// *内容为TaskRunner对象映象的类型对象
// * 向客户公布的服务名字
// * 对象的模式:Singleton意味着所有客户端请求共享一个对象服务;SingleCall意味着 // 每个客户端请求使用一个新的对象服务。
Console.WriteLine("[i] -- 向远程机制的后端注册TaskRunner对象");
Type theType = new TaskRunner().GetType();
RemotingConfiguration.RegisterWellKnownServiceType(theType, "TaskServer", WellKnownObjectMode.Singleton);
Console.WriteLine("[i] 服务器启动成功,按任何键退出...");
Console.ReadLine();
可就是不行,如果懂的话请留下QQ,我传一份,这样好不? --------------------编程问答-------------------- 那个我也有写的,可就是不行,如果有懂的人情留下QQ,我传一份大家研究一下
// 创建TCP通道
Console.WriteLine("[i] -- 创建TCP通道");
TcpChannel chan = new TcpChannel(8085);
// 向.NET的远程服务注册新创建的TcpChannel,使客户端可以使用这一服务
Console.WriteLine("[i] -- 注册TCP通道");
ChannelServices.RegisterChannel(chan, false);
//向远程机制的后端注册TaskRunner对象,RegisterWellKnownServiceType方法将完成这一 //操作,并接收下面的参数:
// *内容为TaskRunner对象映象的类型对象
// * 向客户公布的服务名字
// * 对象的模式:Singleton意味着所有客户端请求共享一个对象服务;SingleCall意味着 // 每个客户端请求使用一个新的对象服务。
Console.WriteLine("[i] -- 向远程机制的后端注册TaskRunner对象");
Type theType = new TaskRunner().GetType();
RemotingConfiguration.RegisterWellKnownServiceType(theType, "TaskServer", WellKnownObjectMode.Singleton);
Console.WriteLine("[i] 服务器启动成功,按任何键退出...");
Console.ReadLine(); --------------------编程问答-------------------- TaskRunner taskRunner = (TaskRunner)Activator.GetObject(typeof(TaskServer.TaskRunner),
"tcp://localhost:8085/TaskServer");
你客户端这句中的"TaskRunner "和"TaskServer.TaskRunner"是同一个类吗?
----------
三易通软件(服装进销存,服装进销存软件,服装进销存管理软件,服装进销存管理系统,服装店管理软件,服装店管理系统,服装销售管理软件,服装销售管理系统,服装零售管理软件,服装零售管理系统,服装店软件,服装店收银软件):http://www.3etsoft.cn --------------------编程问答-------------------- 没做过remoting的,做过wcf的,帮顶了... --------------------编程问答-------------------- kankan --------------------编程问答-------------------- 你使用了客户端激活,使用这种方式,你必须在客户端的调用路径里有包含了TaskServer.TaskRunner这个类的DLL。
调用路径包括,GAC,程序当前运行路径,config文件里指定的路径。 --------------------编程问答-------------------- 是同一个类 --------------------编程问答-------------------- 楼主把详细的错误贴上来看看吧 --------------------编程问答-------------------- 执行类:
// 该对象用来运行由客户端提交的任务,提交的任务将在服务器的应用域执行。
// 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 interface ITask
{
object Run();
string Identify();
}
public class TaskRunner : MarshalByRefObject
{
ITask remoteTaskObject;
public TaskRunner()
{
Console.WriteLine("\n[i] 服务器启动");
}
public string LoadTask(ITask task)
{
Console.WriteLine("\n[i] 加载新任务...");
if (task == null)
{
Console.WriteLine("[e] 没有任务,无法加载任务.");
return "[e] 任务加载失败.";
}
remoteTaskObject = task;
Console.WriteLine("[i] 任务加载成功.");
Console.WriteLine("[i] 任务编号: " + remoteTaskObject.Identify() + "\n");
return "[i] 任务加载成功,欢迎使用分布式服务器.";
}
public object RunTask()
{
Console.WriteLine("\n[i] 开始执行客户端提交的任务...");
object result = remoteTaskObject.Run();
Console.WriteLine("[i] 任务执行完毕.");
return result;
}
}
}
--------------------编程问答-------------------- 客户端类:
// 这是一个客户端应用域,客户端的任务是建立一个任务对象,并将它提交给任务服务器
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 ("这是一个乘法例子.");
}
}
public class Client
{
public static void Main()
{
Console.WriteLine("\n欢迎使用分布式简单测试例子.\n");
ClientTask clientTask = new ClientTask(100, 100);
try
{
Console.WriteLine("[i] 连接服务器...");
Console.WriteLine("[i] - 打开TCP通道");
TcpChannel chan = new TcpChannel();
Console.WriteLine("[i] - 注册通道");
ChannelServices.RegisterChannel(chan);
Console.WriteLine("[i] 连接上服务器");
// 从TaskServer中获取TaskRunner对象的引用
// Activator类中的GetObject方法需要二个参数:
// * 对象类型
// * 对象的URI位置
Console.WriteLine("[i] 得到一个新对象提交给服务器");
TaskRunner taskRunner = (TaskServer.TaskRunner)Activator.GetObject(typeof(TaskServer.TaskRunner),
"tcp://localhost:8085/TaskServer");
if (taskRunner == null)
{
Console.WriteLine("[e] 连接不上服务器.");
Console.WriteLine("[i] 退出...");
return;
}
Console.WriteLine("[i] 有一个新对象!");
// 下面我们将把任务对象传递给任务服务器
Console.WriteLine("\n[i] 把任务提交给服务器...");
string response = taskRunner.LoadTask(clientTask);
Console.WriteLine("[i] 服务器收到指令: " + response);
Console.WriteLine("\n[i] 服务器开始执行指令并返回结果...");
object result = taskRunner.RunTask();
Console.WriteLine("[aaa-uuuum] 服务器返回的结果集: " + (int)result);
Console.ReadLine();
}
catch (Exception e)
{
Console.WriteLine("[e] 一个错误.");
Console.WriteLine(e);
}
}
}
}
--------------------编程问答-------------------- 服务器类:
// 这个类用来启动任务服务器应用程序。它建立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()
{
//RemotingConfiguration.Configure(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile, false);
// 向用户表明我们正在启动服务器类
Console.WriteLine("正在启动服务器类!");
Console.WriteLine("....\"客户端的任务是服务器的指令\"....");
Console.WriteLine("\n[i] 开始启动客户端服务器...");
try
{
// 创建TCP通道
Console.WriteLine("[i] -- 创建TCP通道");
TcpChannel chan = new TcpChannel(8085);
// 向.NET的远程服务注册新创建的TcpChannel,使客户端可以使用这一服务
Console.WriteLine("[i] -- 注册TCP通道");
ChannelServices.RegisterChannel(chan, false);
//向远程机制的后端注册TaskRunner对象,RegisterWellKnownServiceType方法将完成这一 //操作,并接收下面的参数:
// *内容为TaskRunner对象映象的类型对象
// * 向客户公布的服务名字
// * 对象的模式:Singleton意味着所有客户端请求共享一个对象服务;SingleCall意味着 // 每个客户端请求使用一个新的对象服务。
Console.WriteLine("[i] -- 向远程机制的后端注册TaskRunner对象");
Type theType = new TaskRunner().GetType();
RemotingConfiguration.RegisterWellKnownServiceType(theType, "TaskServer", WellKnownObjectMode.Singleton);
Console.WriteLine("[i] 服务器启动成功,按任何键退出...");
Console.ReadLine();
}
catch (Exception e)
{
Console.WriteLine("[!] 错误.");
Console.WriteLine(e);
}
}
}
}
--------------------编程问答-------------------- MARK --------------------编程问答-------------------- 楼主,按照你的代码。你是不是只有两个工程?一个是客户端,一个是服务器端?
如果是,你需要建立第三个工程。该工程里声明 ITask接口以及ClientTask类并实现。
然后客户端工程和服务器端工程都必须引用该工程。 --------------------编程问答-------------------- 三个工程 --------------------编程问答-------------------- 或者换句话说,你必须保证ClientTask类在客户端和服务器端都能调用到。
你的想法可能是想在客户端创建一个类的实例,并将该类的实例传给服务器端,在服务器端被执行后返回结果。
但是,这样是无法实现的。因为服务器端即使有了该接口,但是没有该类的声明,所以当该实例被传输到服务器端时,服务器端无法实例化一个对应的类来获取客户端传上来的实例。 --------------------编程问答-------------------- 让我想想,你既然已经有了3个工程,那么
ITask和TaskRunner在一个工程里(A)(A是DLL)
ClientTask和Client在一个工程里(B)(B是EXE)
TaskServerEngine在一个工程里(C)(C是EXE)
所以 B 引用了 A,C 引用 A,而关键了 C 要调用 B 里ClientTask,所以 C 要引用 B。但是C和B都是EXE,他们是不能直接互相引用的。因此C无法在运行是获取ClientTask的一个实例。
所以,我建议你将ITask和ClientTask放到同一个工程里(B),并将该工程设置成DLL,然后A引用B,C引用B。
补充:.NET技术 , C#