天天看点

HOW TO:使用 Visual C# .NET 按值将对象封送到远程服务器 (From MSDN)

本文的发布号曾为 CHS307546 本文讨论一种 Microsoft 产品的 Beta 版本。本文中的信息按“原样”提供,如有更改恕不另行通知。

对于该 Beta 产品,Microsoft 不提供正式的产品支持。有关获取对 Beta 版本的支持的信息,请参阅 Beta 产品文件中包括的文档资料,或查看您下载此版本的站点。

有关本文的 Microsoft Visual Basic .NET 版本,请参见 301116。

本任务的内容

  • 摘要
    • 要求
    • 创建远程服务器对象
    • 创建远程服务器应用程序
    • 创建客户机应用程序
  • 参考

概要

本文演示如何按值将对象封送到远程服务器。 在按值封送对象时,就会创建一个该对象的副本,并将其序列化传送到服务器。 任何对该对象的方法调用都是在服务器上进行的。 因为需要将对象序列化传送到服务器,所以,必须使用 [Serializable] 属性修饰要传递对象的类定义。

本文阐述了下列 Microsoft 知识库文章中描述的一些概念:

  • 300951 HOW TO: Create a Remote Server Using Visual Basic .NET(HOW TO:使用 Visual Basic .NET 创建远程服务器)
  • 300943 HOW TO: Create a Client to a Remote Server Using Visual Basic .NET(HOW TO:使用 Visual Basic .NET 创建到远程服务器的客户机)

备注: 完成本文中的步骤 不 需要阅读这些文章。

返回页首

要求

下表概括了推荐使用的硬件、软件、网络架构以及所需的 Service Pack:

  • Microsoft Windows 2000 Professional、Windows 2000 Server、Windows 2000 Advanced Server 或 Windows NT 4.0 Server
  • Microsoft Visual Studio .NET

本文假定您熟悉下列主题:

  • Visual Studio .NET
  • 网络基础知识

返回页首

创建远程服务器对象

创建服务器应用程序的第一步是创建服务器对象。服务器对象在服务器上,客户机应用程序要实例化它并与之通讯。客户机应用程序是通过客户机上创建的代理对象实现这一点的。您的名为 HelloServer 的服务器对象将放在一个类库 (DLL) 中。 在同一个项目中,还定义将从客户机传递到服务器的类。此类名为 ForwardMe。 因为您希望按值封送 ForwardMe 类,所以,需要使用 [Serializable] 属性修饰 ForwardMe 类。

  1. 打开 Visual Studio .NET。
  2. 新建一个 Visual C# .NET 类库应用程序。默认情况下创建 Class1.cs。
  3. 在解决方案资源管理器中,将 Class1.cs 文件重命名为 ServerClassValue.cs。
  4. 打开 ServerClassValue.cs。导入 System.Diagnostics 名称空间,这样,以后就不需要在代码中完全限定名称了。
    using System;
    using System.Diagnostics;      
  5. 添加两个类,即 HelloServer 和 ForwardMe。 HelloServer 是从 MarshalByRefObject 类继承的,而且 ForwardMe 类使用 <Serializable> 自定义属性。 在将对象按值传递到远程服务器时,此标记允许将 ForwardMe 类以流的形式输入和输出服务器。

    HelloServer 是客户机应用程序使用的主类。ForwardMe 用来将对象数据从客户机发送到服务器。 因为 ForwardMe 不是从 MarshalByRefObject 继承的,所以将它按值传递到服务器。

    public class HelloServer : MarshalByRefObject
    {
    }
    
    [Serializable]
    public class ForwardMe
    {
    }      
  6. 将公用方法 HelloMethod 添加到 HelloServer,后者将 ForwardMe 对象作为参数。 使用此方法将 ForwardMe 对象传递到服务器。此方法调用这一对象的 CallMe 方法。您的 HelloServer 类现在应该如下所示:
    public class HelloServer : MarshalByRefObject
    {
    	public void HelloMethod(ForwardMe obj )
    	{
               obj.CallMe();
    	}
    }       
  7. 将一个公用方法添加到 ForwardMe 类,并根据执行此代码的进程来命名此方法。 因为您将整个对象序列化传递到服务器(按值封送),所以此代码在服务器的进程中运行。
    [Serializable]
    public class ForwardMe
    {
    	public void CallMe() 
    	{
    		 Console.WriteLine("CallMe was executed in: " +
    			Process.GetCurrentProcess().ProcessName.ToString());
    	}							
    }      
  8. 生成该项目以创建 ServerClassValue.dll 程序集。
  9. 保存并关闭该项目。

返回页首

创建远程服务器应用程序

在创建了客户机将与之通讯的服务器对象后,必须将此对象注册到远程处理框架中。注册不仅包括对对象进行注册,还包括启动服务器并让它侦听一个端口以便客户机进行连接。为此,您需要一个能创建可执行文件的项目类型。 将服务器对象包含在另一个项目中,以便能方便地从客户机引用服务器对象。如果您在此项目中包括了服务器对象,您不能引用它,因为只可以设置到 DLL 文件的引用。

  1. 打开 Visual Studio .NET。
  2. 新建一个 Visual C# .NET 控制台应用程序以启动远程服务器。默认情况下创建 Class1.cs。
  3. 在解决方案资源管理器中,将 Class1.cs 文件重命名为 ServerObjectValue.cs。
  4. 给项目添加一个到 System.Runtime.Remoting 名称空间的引用。
  5. 添加对 ServerClassValue.dll 程序集(在创建远程服务器对象一节中创建的)的引用。
  6. 对 Remoting、Remoting.Channels 和 Remoting.Channels.Tcp 名称空间使用 using 语句,这样,在后面的代码中就不需要限定这些名称空间中的声明了。using 语句必须位于所有其他声明之前。
    using System.Runtime.Remoting;
    using System.Runtime.Remoting.Channels;
    using System.Runtime.Remoting.Channels.Tcp;      
  7. 声明相应的变量以初始化一个 TcpChannel 对象,该对象监听某个端口以便客户机进行连接(本例中为 8085 端口)。使用 RegisterChannel 方法注册客户机将用来与通道服务进行通讯的通道。在 Module1 的 Main 过程中添加声明代码:
    TcpChannel chan = new TcpChannel(8085);
    ChannelServices.RegisterChannel(chan);      
  8. 调用 RemotingConfiguration 对象的 RegisterWellKnownType 方法,将 ServerClassValue 对象注册到远程处理框架中。在代码中必须指定下列参数:
    1. 正在注册的对象的完整类型名称(本例中是 ServerClassValue.HelloServer),后面跟着程序集名称 ServerClassValue。必须指定名称空间的名称和类名。因为在前面的部分中没有指定名称空间,所以使用默认的根名称空间。
    2. 对象将要发布到的终结点的名称。客户机需要知道此名称以便连接到该对象。 请使用 RemoteTestValue。
    3. 对象模式,可以是 SingleCall 或 Singleton。本例指定 SingleCall。对象模式指定了在服务器上激活该对象时的有效期。对于 SingleCall 对象,针对客户机的每次调用都会创建类的一个新实例,即使在同一客户机多次调用同一方法的情况下也是如此。或者,只创建一次 Singleton 对象,所有客户机都与同一个对象通讯。
    RemotingConfiguration.RegisterWellKnownServiceType(
    	Type.GetType("ServerClassValue.HelloServer, ServerClassValue"),
    	"RemoteTestRef",
    	WellKnownObjectMode.SingleCall);      
  9. 使用 Console 对象的 ReadLine 方法保持服务器应用程序的运行:
    Console.WriteLine("Press <ENTER> to exit...");
    Console.ReadLine();       
  10. 生成项目。
  11. 保存并关闭项目。

返回页首

创建客户机应用程序

  1. 打开 Visual Studio .NET。
  2. 在 Visual C# .NET 中新建控制台应用程序。默认情况下创建 Class1.cs。
  3. 在解决方案资源管理器中,将 Class1.cs 文件重命名为 ClientAppValue.cs。
  4. 给项目添加一个到 System.Runtime.Remoting 名称空间的引用。
  5. 添加对 ServerClassValue.dll 程序集(在创建远程服务器对象一节中创建的)的引用。
  6. 对 Remoting、Remoting.Channels 和 Remoting.Channels.Tcp 名称空间使用 using 语句,这样,在后面的代码中就不需要限定这些名称空间中的声明了。using 语句必须位于所有其他声明之前。
    using System.Runtime.Remoting;
    using System.Runtime.Remoting.Channels;
    using System.Runtime.Remoting.Channels.Tcp; 
    using ServerClassValue;      
  7. 声明相应的变量以初始化一个 TcpChannel 对象,客户机将使用该对象连接到服务器应用程序。使用 RegisterChannel 方法将该通道注册到通道服务。

    然后,必须初始化一个新的 ForwardMe 对象,该对象将被传递到远程服务器对象。 切记,将按值传递该对象。在 Module1 的 Main 过程中添加声明代码:

    TcpChannel chan = new TcpChannel();
    ChannelServices.RegisterChannel(chan);
    ForwardMe objForwardMe  = new ForwardMe();      
  8. 声明和实例化远程服务器。在本例中,使用 Activator 对象的 GetObject 方法实例化 HelloServer 对象。在代码中必须指定下列参数:
    1. 正在注册的对象的完整类型名称(本例中是 ServerClassValue.HelloServer),后面跟着程序集名称 ServerClassValue。必须指定名称空间的名称和类名。因为在前面的部分中没有指定名称空间,所以使用默认的根名称空间。
    2. 要激活的对象的统一资源标识符 (URI)。 URI 必须包含协议 (tcp)、计算机名 (localhost)、端口 (8085) 和服务器对象的终结点 (RemoteTestValue)。 若要访问位于本地服务器上的 ServerClassValue 远程服务器,URI 为 tcp://localhost:8085/RemoteTestValue。
    HelloServer objHelloServer;
    
    objHelloServer = (HelloServer)Activator.GetObject(
    		typeof(HelloServer),
    		"tcp://localhost:8085/RemoteTestRef");
    if (objHelloServer == null)
    	Console.WriteLine("Could not locate server");
    else
    {
    	//See next step
    }       
  9. 如果服务器对象实例化成功,则调用服务器对象的 HelloMethod ,并将新创建的 objForwardMe 对象传递给该方法。

    切记,HelloMethod 调用 ForwardMe 对象的 CallMe 方法,该方法向控制台窗口显示运行该代码所在进程的名称。

    HelloServer objHelloServer;
    
    objHelloServer = (HelloServer)Activator.GetObject(
    		typeof(HelloServer),
    		"tcp://localhost:8085/RemoteTestRef");
    if (objHelloServer == null)
    	Console.WriteLine("Could not locate server");
    else
    {
    	objHelloServer.HelloMethod(objForwardMe);
            Console.WriteLine("Method executed, check server window for output.");
    }      
  10. 使用 Console 对象的 ReadLine 方法保持客户机应用程序的运行:
    Console.WriteLine("Press <ENTER> to exit...");
    Console.ReadLine();       
  11. 生成项目。
  12. 确保服务器应用程序在运行中。
  13. 运行客户机项目以测试客户机和服务器之间的通讯。

运行客户机时,当该方法执行结束时,您就会收到通知。 注意, CallMe 方法的输出结果显示在服务器的控制台窗口中,而不是显示在客户机的控制台窗口中。这是因为对象是按值封送到服务器的。

返回页首

参考

有关 TcpChannel 类的更多信息,请访问以下 .NET 框架类程序库 Web 站点:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfSystemRuntimeRemotingChannelsTcpTcpChannelClassTopic.asp

有关 RegisterWellKnownServiceType 方法的更多信息,请访问以下 .NET 框架类程序库 Web 站点:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfSystemRuntimeRemotingRemotingConfigurationClassRegisterWellKnownServiceTypeTopic.asp

有关 Microsoft .NET 远程处理框架的介绍(一般性的 .NET 开发技术文章),请访问以下 MSDN 站点:

http://msdn.microsoft.com/library/techart/remoting.htm

返回页首

这篇文章中的信息适用于:

  • Microsoft Visual C# .NET Beta 2
最近更新: 2001-11-5 (1.0)
关键字 kbDSupport kbhowto kbHOWTOmaster kbnokeyword KB307546 kbAudDeveloper