65.9K
CodeProject 正在变化。 阅读更多。
Home

简单的Remoting HelloWorld

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.79/5 (25投票s)

2005年5月1日

4分钟阅读

viewsIcon

218750

downloadIcon

7426

在本文中,我将解释如何使用 Framework 1.1 在 VB.NET 中进行远程处理。

Sample Image - Remoting_HelloWorld.jpg

引言

搜索了很多,我没有找到一个真正简单的远程处理示例来展示我所教授的课程,所以我决定发表我自己的文章,介绍如何以简单的方式进行远程处理。

首先,本文基于 VB.NET 使用 .NET Framework 1.1 (Visual Studio 2003)。

我将解释如何使用 Remoting 与组件进行通信,我现在将对远程处理做一个简要介绍。

在过去,当应用程序开发开始时,我们使用 COM,它允许我们将 UI 应用程序与功能库 (DLL) 分离。之后我们有了 DCOM,它允许我们在不同计算机上的两个不同组件之间进行通信。DCOM 是一种非常专有的基于 RPC 的通信协议,用于基于 COM 的分布式组件架构。尽管 DCOM 允许我们在 Intranet 环境中创建可伸缩且可靠的架构,但在尝试将其与 Internet 环境中的不同平台和技术集成时,DCOM 会遇到很多问题。

现在有了新的 .NET 技术,我们有了 WebServices.NET Remoting。Web 服务允许我们使用标准的 HTTP 和 SOAP 在不同平台和技术之间进行通信,这非常好,而且非常容易实现。但是,当您想使用 .NET 进行 状态管理 时,Web 服务存在一些不足。Remoting 通过 Singleton 和 SingleCall 对象为有状态和无状态环境提供支持。

谈到 类型系统,Web 服务仅支持 XSD 类型系统中定义的 数据类型,限制了可序列化的对象数量,而 .NET Remoting 使用二进制通信,提供对丰富类型系统的支持。当然,Web Services 相比 .NET Remoting 也有一些优点,例如互操作性,提供跨平台互操作性支持(非常适合异构环境),而 .NET Remoting 要求客户端必须使用 .NET 构建。

尽管 .NET Remoting 基础结构和 ASP.NET Web 服务都可以实现跨进程通信,但它们各自的目标受众不同。

对于需要互操作性并在公共网络上运行的应用程序,Web 服务可能是最佳选择。对于需要与其他 .NET 组件通信且性能是关键优先事项的应用程序,.NET Remoting 是最佳选择。

现在让我们来谈谈我们的解决方案!!因为 Remoting 对象默认情况下不会激活,我们需要创建一个 应用程序主机域(这是微软的称呼),以便将我们公开的库加载到内存中,并将其公开为远程对象。我们的解决方案将包含四个项目,如下所示。

  1. IRemoteLib:这将是一个示例接口,客户端和服务器部分都将使用它。
  2. LibraryExposed:这是 IRemoteLib 的实现,它将继承自 MarshalByRefObject,这里包含了客户端使用的所有方法。
  3. EasyInvoke:这是一个 WinForm 应用程序(它是我们的 应用程序主机域实现),它将加载 LibraryExposed 并将其公开给我们的客户端。我们将我们的库实例创建为 服务器激活对象,并使用 Singleton 激活(singletonsingle call 之间的区别在于生命周期管理。Single-call 对象本质上是无状态的,而 singleton 是有状态对象,这意味着它们可以用于在多次方法调用之间保留状态。Singleton 类型在任何时候只有一个实例,所有客户端共享同一个实例,而 SingleCall 类型每个客户端请求始终有一个实例)。
  4. ClientApplication:这是一个将调用远程对象的 WinForm 应用程序。

使用代码

现在让我们开始编写源代码。首先,我们需要创建我们的接口 (IRemoteLib)。

Public Interface IRemoteLib


  ' This event will be used at server to inform every connection
  Event LibCalled(ByVal message As String) 

  ' Call to Hello World Method
  Sub HelloWorldMethod()

  ' Call to Hello World Function
  Function HelloWorld() As String

End Interface

现在我们继续实现 (LibraryExposed)。

Public Class RemoteLib
  Inherits MarshalByRefObject
  Implements IRemoteLib
  Public Event LibCalled(ByVal Message As String) Implements IRemoteLib.LibCalled
    '---------------------------------------
  Public Function HelloWorld() As String Implements IRemoteLib.HelloWorld 
    RaiseEvent LibCalled("Call HelloWorld ")
    Return "Hello World"
  End Function
  Public Sub HelloWorldMethod() Implements IRemoteLib.HelloWorldMethod
    RaiseEvent LibCalled("Call HelloWorldMethod ") 
  End Sub
End Class

正如你所见,一切都很简单,只需注意 Inherits MarshalByRefObject。这就是我们指定这是一个远程对象的地方。我们这样做是因为我们想要指定一个 singleton,并且我们希望客户端使用代理类来访问远程对象。

现在我们来实现 EasyInvoke(因为它是一个 WinForm,您需要先创建一个 WinForm,其中只包含一个停靠的 ListBox)。这是 LibraryExposed 远程对象的激活。

Dim objServer As IRemoteLib
Private Sub Form1_Load(ByVal sender As System.Object, _
       ByVal e As System.EventArgs) Handles MyBase.Load
  Try
    Dim ServiceChannel As IChannel
    Dim serverProv As BinaryServerFormatterSinkProvider = _
             New BinaryServerFormatterSinkProvider 
    Dim clientProv As BinaryClientFormatterSinkProvider = _
             New BinaryClientFormatterSinkProvider
    Dim Props As IDictionary = New Hashtable
    Dim IpInjProvider As New IpInjectorSinkProvider
    serverProv.TypeFilterLevel = _
        System.Runtime.Serialization.Formatters.TypeFilterLevel.Full
    Props("port") = "8000"
    Props("name") = "EasyInvoke"
    ServiceChannel = New TcpChannel(Props, clientProv, serverProv)
    '---------------------------------------------
    ChannelServices.RegisterChannel(ServiceChannel)
    RemotingConfiguration.RegisterWellKnownServiceType( _
                  GetType(RemoteLib), _
                  "EasyInvoke", WellKnownObjectMode.Singleton)
    lstConsole.Items.Add("RemoteLib Started as remoting") ' This is the listbox
    '----------------------------------------------------------
    Init() '--------->> this will be used to catch the events from remote object
  Catch ex As Exception
    lstConsole.Items.Add("Error:" + ex.Message)
  End Try
End Sub

这就是如何将我们的 LibraryExposed 注册为远程对象。现在,让我们完成我们的服务器,其中将添加一项增强功能,允许我们检索哪个客户端正在连接以及我们的远程对象正在使用哪个方法。

'---------------------------------------------------------------
Private Sub Init()
  Dim server As IRemoteLib
  Dim Channel As System.Runtime.Remoting.Channels.tcp.TcpChannel 
  Dim serverProv As BinaryServerFormatterSinkProvider = _
         New BinaryServerFormatterSinkProvider
  Dim clientProv As BinaryClientFormatterSinkProvider = _
         New BinaryClientFormatterSinkProvider
  Dim props As IDictionary = New Hashtable
  serverProv.TypeFilterLevel = _
         System.Runtime.Serialization.Formatters.TypeFilterLevel.Full
  props("port") = 0
  Channel = New System.Runtime.Remoting.Channels.tcp.TcpChannel(props, _
              clientProv, serverProv)
  ChannelServices.RegisterChannel(Channel)
  Try
    server = CType(Activator.GetObject(GetType(IRemoteLib), _
             "tcp://:8000/EasyInvoke"), IRemoteLib)
    If server Is Nothing Then
      MsgBox("server not found or bad initialized!")
    End If
    server.HelloWorldMethod()
  Catch ex As Exception
    Debug.WriteLine(ex.Message)
  End Try
  
  'This is where we say how to handle events from the remote object
  AddHandler server.LibCalled, AddressOf ReceiveLibCall 

End Sub
<System.Runtime.Remoting.Messaging.OneWay()> _
Public Sub ReceiveLibCall(ByVal message As String)
  lstConsole.Items.Add(message)
End Sub

在这里,我们在服务器端添加了一项增强功能,只是为了监听来自远程对象的事件,以便在我们的 ListBox (lstConsole) 中显示哪个方法被客户端使用。

现在是 ClientApplication 的实现。

您应该创建一个 WinForm,其中包含三个按钮:一个连接按钮 (butConnect),一个 HelloWorldSub 按钮 (butHelloWorldSub),以及一个 HelloworldFunc 按钮 (butHelloWorldFunc),然后添加此代码。

Private server As IRemoteLib
Private Channel As System.Runtime.Remoting.Channels.tcp.TcpChannel 
Private serverProv As BinaryServerFormatterSinkProvider
Private clientProv As BinaryClientFormatterSinkProvider
Private props As IDictionary = New Hashtable

Private Sub SetChannel()
  serverProv = New BinaryServerFormatterSinkProvider
  clientProv = New BinaryClientFormatterSinkProvider
  serverProv.TypeFilterLevel = _
      System.Runtime.Serialization.Formatters.TypeFilterLevel.Full
  props("port") = 0
  Channel = New TcpChannel(props, clientProv, serverProv)
End Sub
Private Sub Init()
  SetChannel()
  ChannelServices.RegisterChannel(Channel)
  Try
    server = CType(Activator.GetObject(GetType(IRemoteLib), _
           "tcp://:8000/EasyInvoke"), IRemoteLib)
    If server Is Nothing Then
      MsgBox("server not found!")
    End If
  Catch ex As Exception
    MsgBox(ex.Message)
  End Try
End Sub

现在来实现按钮的点击事件。

Private Sub butHelloWorldSub_Click(ByVal sender As System.Object, _
      ByVal e As System.EventArgs) Handles butHelloWorldSub.Click
  Try
    server.HelloWorldMethod()
  Catch ex As Exception
    MsgBox(ex.Message)
  End Try
End Sub
Private Sub butHelloWorldFunc_Click(ByVal sender As System.Object, _
      ByVal e As System.EventArgs) Handles butHelloWorldFunc.Click
  Try
    MsgBox(server.HelloWorld)
  Catch ex As Exception
    MsgBox(ex.Message)
  End Try
End Sub
Private Sub butConnect_Click(ByVal sender As System.Object, _
      ByVal e As System.EventArgs) Handles butConnect.Click
  If butConnect.Text = "Connect" Then
    Init()
    butConnect.Text = "Disconnect"
    butHelloWorldFunc.Enabled = True
    butHelloWorldSub.Enabled = True
  Else
    ChannelServices.UnregisterChannel(Channel)
    butHelloWorldFunc.Enabled = False
    butHelloWorldSub.Enabled = False
    server = Nothing
    Channel = Nothing
    serverProv = Nothing
    clientProv = Nothing
    butConnect.Text = "Connect"
  End If
End Sub

各位,这就是全部内容!希望大家喜欢!

© . All rights reserved.