Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

A simple Remoting HelloWorld

0.00/5 (No votes)
1 May 2005 1  
In this article, I will explain how to do remoting in VB.NET using Framework 1.1.

Sample Image - Remoting_HelloWorld.jpg

Introduction

Searching a lot, I didn't found a really easy remoting sample to show in the courses that I do, so I decide to publish my own article on how to do remoting in an easy way.

First of all, this article is based in VB.NET using .NET Framework 1.1 (Visual Studio 2003).

I will explain how can you do communication with components using Remoting, I will do a brief introduction to remoting now:

At old times, when application development started, we worked with COM, which allowed us to separate UI applications from functional libraries (DLLs). Later we received DCOM that allowed us to communicate between two different components in different computers. DCOM is a very proprietary RPC-based communication protocol for COM-based distributed component architectures. Even though DCOM allows us to create scalable and reliable architectures in the Intranet environment, there are a lot of problems with DCOM when you try to integrate it with different platforms and technologies in an Internet environment.

Now with the new .NET technologies, we receive WebServices and .NET Remoting. The web services allow us to communicate between different platforms and technologies, using standards HTTP and SOAP, that are very good, and very easy to implement. But web services lack some points when you want to work with State Management with .NET. Remoting provides support for both stateful and stateless environments through Singleton and SingleCall objects.

Talking about Type Systems Web services support only the data types defined in the XSD type system, limiting the number of objects that can be serialized, while .NET Remoting uses binary communication, providing support for rich type system. Of course that Web Services has some better points than .NET Remoting, as for example the Interoperability, providing support to interoperability across platforms (ideal for heterogeneous environments), while .NET Remoting requires the client be built using .NET.

Though both the .NET Remoting infrastructure and ASP.NET Web services can enable cross-process communication, each is designed to benefit a different target audience.

For applications that require interoperability and must function over public networks, Web services are probably the best bet. For those that require communications with other .NET components and where performance is a key priority, .NET Remoting is the best choice.

Now let's talk about our solution!! Because Remoting object will not be active by default, we need to create an Application Host Domain (this is how MS calls them), in order to load our exposed library in memory, and expose it as a Remote object. Our solution will consist of four projects, as follows:

  1. IRemoteLib: This will be a sample interface, that will be used by the client and the server part.
  2. LibraryExposed: is the IRemoteLib implementation and it will inherit from MarshalByRefObject, here are all the methods used by the client.
  3. EasyInvoke: This is a WinForm application (it's our Application Host Domain implementation) that will load LibraryExposed and will expose it to our client. We will instance our library as Server-activated object as Singleton activation (the difference in a singleton and single call lies in lifetime management. While single-call objects are stateless in nature, singletons are stateful objects, meaning that they can be used to retain state across multiple method calls. Singleton types never have more than one instance at any one time, sharing the same instance between all clients, while SingleCall types always have one instance per client request).
  4. ClientApplication: This is a WinForm application that will call the remote object.

Using the code

Now let's start with source code. First of all, we need to create our Interface (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

Now let's continue with the implementation (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

As you see everything is very easy, just pay attention at Inherits MarshalByRefObject. This is where we specified that this will be a remoting object. We do it this way, because we want to specify a singleton, and we want that the client access the remote object using a proxy class.

Now let's implement the EasyInvoke (because it's a WinForm, you need first to create a WinForm, just with a ListBox docked at it). This is the LibraryExposed remote object activation:

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

This was how to register our LibraryExposed as a remote object. Now let's finish our server as an enhancement that will allow us to retrieve which client is connecting and which method is using our remote object.

'---------------------------------------------------------------

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://localhost: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

Here we add an enhancement to our server side, just to listen the events from the remote object to display which method is in use by the client at our ListBox (lstConsole).

And now the ClientApplication implementation:

You should create a WinForm with three buttons, one connect button (butConnect), one HelloWorldSub button (butHelloWorldSub), and one HelloworldFunc button (butHelloWorldFunc) and add this code:

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://localhost: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

And now implement the buttons click:

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

That's all folks! I hope you enjoy it!

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here