Getting Started with .Net Remoting

Hmanjarawala
Posted by in .NET Framework category on for Beginner level | Points: 250 | Views : 5246 red flag

This article contains sampleapplication, which demonstrate how .Net remoting works


 Download source code for Getting Started with .Net Remoting

Introduction


.Net Remoting provides mechanism to communicate with object beyond the application context boundary. This application context known as AppDomain. It is a generic system for different applications to communicate with one another. Object exposes their processes called Remote methods for interprocess communication. Application might be hosted in same network or some remote location, either through intranet or Internet.

.Net remoting provides framework that allow objects to interact with each other across application domain. Remoting was designed in a way that it hides the most difficult aspects like managing connections, marshaling data, and reading and writing XML and SOAP. The framework provides a number of services, including object activation and object lifetime support, as well as communication channels which are responsible for transporting messages to and from remote applications.


Remote Object


Any object, outside the application domain of caller application called remote object. Local object that cannot be serialized cannot be passed to different application domain, hence cannot be remote object.

Any object can be changed into a remote object by deriving it from MarshalByRefObject, or by making it serializable either by adding the [Serializable] tag or by implementing the ISerializable interface. When a client activates a remote object, it receives a proxy to the remote object. All operations on this proxy are appropriately indirected to enable the Remoting infrastructure to intercept and forward the calls appropriately. In cases where the proxy and remote objects are in different application domains, all method call parameters on the stack are converted into messages and transported to the remote application domain, where the messages are turned back into a stack frame and the method call is invoked. The same procedure is used for returning results from the method call.

Using the code

Here is a sample aplication for that. Each remoting application contains three parts:

1.       Client

2.       Remote Object

3.       Server.

Lets start with Remote object first.

Public Interface IObserver

    Function InvokeMethod() As String

    Function InvokeMethod(ByVal number1 As Integer, ByVal number2 As Integer, ByVal [operator] As Integer) As String

End Interface

Here is an interface Iobserver that contains methods that’s are shared between the client and the server.

Public Class RemoteMyObject

    Inherits MarshalByRefObject

    Implements IDisposable

 

 

    Public Sub New()

    End Sub

 

    Public Function Method1() As String

        Method1 = Cache.CreateInstance.MyMethod1

    End Function

 

    Public Function Method2(ByVal number1 As Integer, ByVal number2 As Integer, ByVal [operator] As Integer) As String

        Method2 = Cache.CreateInstance.MyMethod2(number1, number2, [operator])

    End Function

 

    Public Function Method3(ByVal clientId As Integer) As String

        Method3 = Cache.CreateInstance.MyMethod3(clientId)

    End Function

 

    Private disposedValue As Boolean = False        ' To detect redundant calls

 

    ' IDisposable

    Protected Overridable Sub Dispose(ByVal disposing As Boolean)

        If Not Me.disposedValue Then

            If disposing Then

                ' TODO: free other state (managed objects).

                Console.WriteLine("RemoteObject is Distroying")

            End If

 

            ' TODO: free your own state (unmanaged objects).

            ' TODO: set large fields to null.

        End If

        Me.disposedValue = True

    End Sub

 

#Region " IDisposable Support "

    ' This code added by Visual Basic to correctly implement the disposable pattern.

    Public Sub Dispose() Implements IDisposable.Dispose

        ' Do not change this code.  Put cleanup code in Dispose(ByVal disposing As Boolean) above.

        Dispose(True)

        GC.SuppressFinalize(Me)

    End Sub

#End Region

 

End Class

 

Here is a sample Remote class, as we already discussed local objects that cannot be serialized cannot be remote object, so to make this class serializable we derived this from MarshelByRefObject. You also noticed what is Cached? It’s a single tone class that is define as below. Singletone class is a class that cannot be instanciate directly through constructor.


Public Class Cache

    Private Shared _myInstance As Cache

    Private Shared _Observer As Iobserver

 

    Private Sub New()

    End Sub

 

    Public Shared Sub Attach(ByVal observer As IObserver)

        _Observer = observer

    End Sub

 

Public Shared Function CreateInstance() As Cache

        If _myInstance Is Nothing Then

            _myInstance = New Cache

        End If

        Return _myInstance

    End Function

 

    Public Function MyMethod1() As String

        MyMethod1 = _Observer.InvokeMethod

    End Function

 

    Public Function MyMethod2(ByVal number1 As Integer, ByVal number2 As Integer, ByVal [operator] As Integer) As String

        MyMethod2 = _Observer.InvokeMethod(number1, number2, [operator])

    End Function

End Class

 

As per discussed instace of this class can be generated from CreateInstance() method. So this is first and most important part of our application. You might think why important? Because both client and server application use this objects for communication. You might think why don’t common class library project developed and distributed between client and server. Because it’s not a good programing practice to shared business logic to client side, that’s why we developed interface to hide bussiness intelegence.

Now lets design server side object. Remote server is console application that register Remote object as some well known service. Lets see how to do that. For this first develop remote class that implement Iobserver interface.

Imports System

Imports System.IO

Imports System.Runtime.InteropServices

Imports RemotableObject

 

Public Class MyObject

    Implements IObserver

    Implements Idisposable

 

    Public Function InvokeMethod() As String Implements RemotableObject.IObserver.InvokeMethod

        Console.WriteLine("Invoke 1 Method Called....")

        InvokeMethod = "This is Invoke 1 Method"

    End Function

 

Public Function InvokeMethod(ByVal number1 As Integer, ByVal number2 As Integer, ByVal [operator] As Integer) As String Implements RemotableObject.IObserver.InvokeMethod

        Dim output As String = "Output: {0} {1} {2} = {3}"

        Select Case [operator]

            Case 1

                output = String.Format(output, number1, "+", number2, (number1 + number2))

            Case 2

                output = String.Format(output, number1, "-", number2, (number1 - number2))

            Case 3

                output = String.Format(output, number1, "X", number2, (number1 * number2))

            Case Else

                output = String.Format(output, number1, "/", number2, (number1 / number2))

        End Select

        Console.WriteLine(output)

        InvokeMethod = output

    End Function

 

    Private disposedValue As Boolean = False        ' To detect redundant calls

 

    ' IDisposable

    Protected Overridable Sub Dispose(ByVal disposing As Boolean)

        If Not Me.disposedValue Then

            If disposing Then

                ' TODO: free other state (managed objects).

                Console.WriteLine("MyObject is Distroying")

            End If

 

            ' TODO: free your own state (unmanaged objects).

            ' TODO: set large fields to null.

        End If

        Me.disposedValue = True

    End Sub

 

#Region " IDisposable Support "

    ' This code added by Visual Basic to correctly implement the disposable pattern.

    Public Sub Dispose() Implements IDisposable.Dispose

        ' Do not change this code.  Put cleanup code in Dispose(ByVal disposing As Boolean) above.

        Dispose(True)

        GC.SuppressFinalize(Me)

    End Sub

#End Region

 

End Class

 

Imports System.Runtime.Remoting

Imports System.Runtime.Remoting.Channels

Imports System.Runtime.Remoting.Channels.Tcp

Imports RemotableObject

 

Module Module1

    <STAThread()> _

    Sub Main()

        Dim RemoteMyObject As New RemoteMyObject

        '************************************* TCP *************************************

        ' using TCP protocol

        Dim channel As New TcpChannel(8080)

        ChannelServices.RegisterChannel(channel, False)

        RemotingConfiguration.RegisterWellKnownServiceType(GetType(RemoteMyObject), "RemoteObject.rem", WellKnownObjectMode.Singleton)

        '************************************* TCP *************************************

        Cache.Attach(New MyObject)

        Cache.Attach(New MyClient)

        Console.Out.WriteLine("Server is Ready to Accept Request")

        While Console.Read()

            Exit While

        End While

    End Sub

 

End Module

So here is our remote server is ready. When you run this application it will look like this.

Now last but not least start developing the client.

Imports RemotableObject

Imports System.Runtime.Remoting

Imports System.Runtime.Remoting.Channels

Imports System.Runtime.Remoting.Channels.Tcp

 

Public Class Form1

 

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

 

    End Sub

 

    Private Sub ExportButton1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ExportButton1.Click

        '************************************* TCP *************************************

        ' using TCP protocol

        ' running both client and server on same machines

 

        Dim chan As New TcpChannel()

        ChannelServices.RegisterChannel(chan, False)

        ' Create an instance of the remote object

        Dim remoteOITExport As RemoteMyObject

 

        Try

            remoteOITExport = TryCast(Activator.GetObject(GetType(RemoteMyObject), "tcp://dell6:8080/RemoteObject.rem"), RemoteMyObject)

 

            OutputMessage.Text = OutputMessage.Text & vbCrLf & remoteOITExport.Method1

 

        Catch ex2 As Net.Sockets.SocketException

            MessageBox.Show(ex2.Message)

        Catch ex1 As RemotingTimeoutException

            MessageBox.Show(ex1.Message)

        Catch ex As RemotingException

            MessageBox.Show(ex.Message)

        Finally

            remoteOITExport = Nothing

            ChannelServices.UnregisterChannel(chan)

            chan = Nothing

        End Try

    End Sub

 

    Private Sub ExportButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ExportButton.Click

        '************************************* TCP *************************************

        ' using TCP protocol

        ' running both client and server on same machines

 

        Dim chan As New TcpChannel()

        ChannelServices.RegisterChannel(chan, False)

        ' Create an instance of the remote object

        Dim remoteOITExport As RemoteMyObject

        Dim number1 As Integer = New Random().Next(50, 99)

        Dim number2 As Integer = New Random().Next(1, 49)

        Dim [operator] As Integer = New Random().Next(1, 10)

 

        Try

            remoteOITExport = TryCast(Activator.GetObject(GetType(RemoteMyObject), "tcp://dell6:8080/RemoteObject.rem"), RemoteMyObject)

 

            OutputMessage.Text = OutputMessage.Text & vbCrLf & remoteOITExport.Method2(number1, number2, [operator])

 

        Catch ex2 As Net.Sockets.SocketException

            MessageBox.Show(ex2.Message)

        Catch ex1 As RemotingTimeoutException

            MessageBox.Show(ex1.Message)

        Catch ex As RemotingException

            MessageBox.Show(ex.Message)

        Finally

            remoteOITExport = Nothing

            ChannelServices.UnregisterChannel(chan)

            chan = Nothing

        End Try

    End Sub

End Class

As you can see it’s a simple windows project having couple of buttons. On each button click channel is registered andclient side proxy of remote object is generated through Activator.GetObject() method. Our user interface will look like this.

     After pressing buttons for Remote Method 1 and Remote Method 2, output is generated on server side.

      

Conclusion

I certainly hope that my article will be of benefit to other readers. I have attempted to present my own research work and share with all my findings.

I also hope that my example code will be of practical use to projects that require some remote controlling of machines. Such remote controlling is not uncommon and is particularly useful in automated systems.

Drop a message to me anytime you have a good suggestion on the example code or on Remoting in general.

Page copy protected against web site content infringement by Copyscape

About the Author

Hmanjarawala
Full Name: Himanshu Manjarawala
Member Level: Bronze
Member Status: Member
Member Since: 7/30/2011 7:42:18 AM
Country: India
Himanshu Manjarawala Sr. Software Engineer@AutomationAnywhere http://fieredotnet.wordpress.com/
http://himanshumbri.blogspot.com
I am Himanshu Manjarawala, Graduate in Computer Science and MCA From Veer Narmad South Gujarat University, Surat Gujarat India. Currently working as Sr. Software Developer in Automation Anywhere.

Login to vote for this post.

Comments or Responses

Posted by: Vuyiswamb on: 1/5/2012 | Points: 25
Very Good article,wished i have such an information before the evolution of WCF.

One more Question ,why would one write a Remoting application if there is WCF ?

Posted by: Hmanjarawala on: 1/6/2012 | Points: 25
Hello sir,

Remoting is usefull in .Net Framework 2.0 where WCF not there, but after framework 3.0 released...there is no need to write Remote application....

Login to post response

Comment using Facebook(Author doesn't get notification)