Using Remoting to Work with Distributed Objects

function OpenWin(url, w, h) { if(!w) w = 400; if(!h) h = 300; window.open(url, "_new", "width=" + w + ",height=" + h + ",menubar=no,toobar=no,scrollbars=yes", true); } function Print() { window.focus(); if(window.print) { window.print(); window.setTimeout('window.close();',5000); } }
Team-Fly    

Special Edition Using Microsoft® Visual Basic® .NET
By Brian Siler, Jeff Spotts
Table of Contents
Chapter 9.  Creating Code Components


As you build and create custom classes, often you will need use these classes in a distributed manner. A typical scenario is when a program on an end user's computer creates a remote instance of an object containing business logic on another computer. A local network or even the Internet might connect these computers. If you were to try to create this type of architecture on your own, you would need to handle a lot of complex administrative tasks: network communications, associating object instances with clients, and so on. Fortunately, the .NET framework provides Remoting, which makes interprocess communication much easier.Remoting abstracts the process of creating objects and using their method calls across network boundaries.

Understanding Remoting Concepts

Although .NET Remoting makes network communication between classes easier, working with remote objects is different enough that you still have to learn a few new concepts.

  • In designing a class that you want to make remotable, you must inherit Remoting functionality from another class.

  • You must be aware that remote objects can be created and destroyed in a manner that is different from local objects.

  • You can make decisions regarding Remoting communications that affect the performance and reach of your remote objects.

After you have mastered these architectural concerns, you will find that the bulk of your code (method calls using an object variable) works the same whether the object is local or remote.

Creating a Remote-Capable Class

When you create an instance of an object locally, the object is stored in local memory until you are through with it, then the garbage collection process releases the associated memory. However, when you create an object remotely, the object is stored in the remote computer's memory, so using its methods involves a lot of communication back and forth across the network. The process of moving an object across the network is known as marshalling the object. All you have to do to make your own class support this process is inherit from the MarshalByRef class, as in the following example:

 Public Class MyBusinessObject      Inherits MarshalByRefObject      Public Sub TestSub(ByVal sInput As String, ByRef sOutput As String)          sOutput = sInput.ToUpper      End Sub  End Class 

The previous code sample uses inheritance to create a class called MyBusinessObject based on the MarshalByRefObject class. The MarshalByRefObject class provides the means by which the object definition and parameters can be transmitted across the network. By adding this single line of code, your class can be activated remotely if desired.

Working with Stateful and Stateless Objects

Remote objects can be created as stateful or stateless. One easy way to understand these concepts is to consider them from the calling program's point of view. For example, consider the following lines of code, which create an instance of a fictional calculator class and then call methods to perform addition:

 Dim MyCalculator As CalcObject  Dim Result As Integer  MyCalculator = New CalcObject()  MyCalculator.Operation = Addition  MyCalculator.EnterNumber(2)  MyCalculator.EnterNumber(3)  Result = MyCalculator.Calculate() 

The preceding code sample first sets the Operation property, then calls the EnterNumber method a couple of times, and finally executes the Calculate function. It seems simple enough, but in order for this code to work, the MyCalculator object must be a stateful object. In other words, it must maintain internal state between each subsequent method call, keeping track of the numbers entered and other properties set by the client. A lot of the objects in Visual Basic work in this same manner, such as the text boxes on your form or variables in your functions. A stateless object, on the other hand, is created only for the time that it takes to execute the current method call and then is immediately destroyed. As a result, its methods are usually written to be processed like transactions:

 Dim MyCalculator As AnotherCalcObject  Dim Result As Integer  MyCalculator = New AnotherCalcObject()  Result = MyCalculator.Calculate(Addition,2,3)  Result = MyCalculator.Calculate(Subtraction,10,5) 

In the second code sample, a stateless version of the Calculator object is called. This code performs the same task, but in a different manner. Instead of executing methods that rely on internal object values, all the information needed for the addition calculation is passed to the object in a single method call. This is because with a stateless remote object, the calling program cannot assume that each time it accesses an object variable, the variable will refer to the same instance of the class. You might think that this is a disadvantage, but actually in some ways it is an advantage! If you are able to write your methods in such a way that each method call is an independent transaction, your client doesn't care which object instance it calls, so the object is free to service other clients, thus making your application more scalable. (And you can always store state on the client using variables or in a back-end database accessed by the stateless object.)

In the .NET Remoting world, the server creates stateless objects in single call mode. For stateful objects, the server can create one single object instance to handle all incoming requests (this is known as singleton mode), or the client can control object instantiation (this is known as client activation). In this section we will focus on stateless objects, because they can be used in more scalable applications. For more information on the other types, see the Help topic "Remoting."

Understanding Channels

Although .NET Remoting hides many of the low-level networking details from the programmer, you still need to be aware of different types of communication channels. A channel is simply a path over the network between two computers. The process of converting an object into a format suitable for transmission across a channel is known as serialization. The two basic types of channels, which use different means of serialization, are listed next:

  • TCP Channels use the TCP/IP protocol to transmit objects as binary data. As with any TCP/IP connection, a machine name (or numeric address) plus a port number is necessary to uniquely identify a channel.

  • HTTP Channels are built on top of TCP/IP, but use text-based data formats such as XML and text-based protocols like SOAP. HTTP channels are a little slower than TCP channels, but are generally more firewall-friendly.

As you might imagine, TCP channels are suited for high-performance intranet communication, while HTTP channels are better for use over the Internet. In this section, we'll focus on TCP channels. Later in the book we will discuss Web Services, which use the HTTP protocol to access remote objects on a Web server.

For more on Web Services, p. 475

Using a Remote Object

Now that you are familiar with the basic concepts, we will build a sample distributed application that uses a remote object. This application will be divided into three parts:

  • The business object is a Windows Class Library project that contains the functionality you want to offer remotely. So that you may learn about the Remoting architecture and apply it to your own programs, the functionality of our example will be a simple temperature conversion class.

  • The host application is a Windows Application project that runs on the server where the business object is located. Its purpose is to set up the communication channel and register the business object with the Remoting framework.

  • The client application is a Windows Application project that runs on the client. It uses the functionality of the remote business object.

Setting Up the Sample Application

To create the sample application, you'll need to perform the following steps:

  1. Start Visual Studio.NET and create a new Windows Class library called TempConverter.

  2. Right-click the solution name and choose to add a new project. Add a Windows Application project called HostApp.

  3. Right-click the solution name and choose to add a new project. Add a Windows Application project called ClientApp.

  4. Right-click the solution name and choose Properties.

  5. From the Properties dialog box, select the option for Multiple Startup Projects.

  6. Set the Action for TempConverter to None. Set the Action for ClientApp and HostApp to Start. This will make both projects start when you begin a debug session in Visual Studio.

Now that you have set up the framework for this example, we will proceed with writing code for each of the three projects in your solution.

Creating the Business Object

First, we'll create the class that contains the heart of the program: the business object. The name business object, incidentally, describes the layer of a multi-tier application that contains logic related to business functionality, rather than database access or the user interface.

For a picture of a multi-tier application, p. 599

To create the example business object, right-click the Class1.vb file in the Solution Explorer and display the Code window. Enter the code from Listing 9.2 to create the clsTemperature class.

Listing 9.2 REMOTING.ZIP Coding the Business Object
 Public Class clsTemperature      Inherits MarshalByRefObject      Public Function CtoF(ByVal CelsuisTemp As Single) As Single          'Converts Celsius temperature to Fahrenheit          Return CelsuisTemp * 9 / 5 + 32      End Function      Public Function FtoC(ByVal FahrenheitTemp As Single) As Single          'Converts Fahrenheit temperature to Celsius          Return (FahrenheitTemp - 32) * 5 / 9      End Function  End Class 

The class definition in Listing 9.2 is just like any other class we have discussed in this chapter, only it inherits from the MarshalByRefObject class. As we mentioned earlier, to create a class that is remotable, all you need to do is add this single line of code. Before continuing with the example,choose Build TempConverter from the Build menu to verify that you do not have any syntax errors.

Importing the Remoting Namespaces

Setting up are motable business object is really easy. As a matter of fact, the business object class is not really aware of Remoting. However, the other parts of the distributed application that host or call remote objects have to be aware of Remoting and network channels. Therefore, you'll need to add references to .NET Remoting classes in both the ClientApp and HostApp projects:

  1. Using the Solution Explorer, right-click the References folder in each project and add a new reference to System.Runtime.Remoting.

  2. Add the following Imports statements to the Form1 class in each project:

     Imports System.Runtime.Remoting  Imports System.Runtime.Remoting.Channels  Imports System.Runtime.Remoting.Channels.Tcp 

After you have added these necessary references, the code in these projects will be able to call methods in .NET Remoting classes.

Setting Up the Host Program

As we mentioned earlier, the class library project itself is not aware of Remoting, so a host program is used to fill in the gaps. The host program opens a communication channel by which a client can request an instance of the business object, and registers the business object type with the Remoting framework. After performing these initial steps, the Remoting framework takes over and handles client requests.

Note

Classes can also be hosted in IIS and exposed as Web Services, eliminating the need to write a custom host program. For more details, see Chapter 18, "Web Applications and Services."


Because the host program will be responsible for registering the class with the Remoting framework, it needs to be aware of the class definition. As you may recall from Chapter 4, "Understanding the Development Environment," to make one project aware of another project in the same solution, you need to add a reference. To add a reference, perform the following steps:

  1. Right-click on References in the HostApp project and choose Add Reference.

  2. From the Add Reference dialog box, select the Projects tab.

  3. Highlight the TempConverter class and click the Select button. Click OK to add the reference.

Next, add two Command buttons to your form. Set their Name properties to btnStart and btnStop. Set their Text properties to Start Service and Stop Service, respectively. Finally, enter the code for the host program, shown in Listing 9.3.

Listing 9.3 REMOTING.ZIP Setting Up the Host Program
 Private Sub btnStart_Click(ByVal sender As System.Object, ByVal e As  System.EventArgs) Handles btnStart.Click      Dim MyChannel As TcpChannel      Dim MyPort As Integer = 12345      Dim MyEndPoint As String = "TempConverter"      Dim MyObjType As System.Type      'Register a TCP Channel      MyChannel = New TcpChannel(MyPort)      ChannelServices.RegisterChannel(MyChannel)      'Register the class      MyObjType = GetType(TempConverter.clsTemperature)      RemotingConfiguration.RegisterWellKnownServiceType _       (MyObjType, MyEndPoint, WellKnownObjectMode.SingleCall)      MessageBox.Show("Server Started!")  End Sub  Private Sub btnStop_Click(ByVal sender As System.Object, ByVal e As  System.EventArgs) Handles btnStop.Click      Application.Exit()  End Sub 

The code for the btnStart event in Listing 9.3 performs two basic tasks: creating a communication channel and registering the object with the Remoting framework. First, the RegisterChannel method is called to set up a new TCP channel on port 12345.

Note

When choosing a port number for a custom application, try to avoid numbers that are established standards (such as 80 for Web browsing or 21 for FTP).


Next, the RegisterWellKnownServiceType method is invoked, which actually makes the object available for remote access. This call has three parameters:

  • The type definition of your business object class.

  • The endpoint string, which is part of the URI (or Uniform Resource Identifier) used to locate a remote object.

  • The object mode, which is set to SingleCall to indicate stateless activation.

Note that the act of creating the channel and registering the object are independent in the code. The channel is just a means of connecting to the Remoting framework. Through the use of the URI string, the Remoting framework can create multiple types of objects using the same channel.

Note

When the host program exits, any Remoting services or channels it created will be destroyed.


Creating the Client Program

The final part of our distributed application is the client process. The client will create a remote instance of the clsTemperature class and call a method to perform the temperature conversion. Before entering the client application code, you will need to add a reference to the TempConverter project, just as we did for the host application. Observant readers may be wondering why this client reference is needed, because the entire purpose of using an object remotely is to not have to install it on the client machine! The answer is that while the client does not require direct access to the object, it still needs to know type information about the object. This type of information, also known as metadata, specifies the method names and parameters of the remote object.

To create the client program, add two text boxes to your form, named txtTempC and txtTempF. Add buttons beside each, named btnConverttoF and btnConvertToC. Finally, enter the code from Listing 9.4.

Listing 9.4 REMOTING.ZIP Setting Up the Client
 Private Function PerformConversion(ByVal ConversionType As String, _     ByVal InputTemp As Single) As Single      'Build URI string      Dim MyPort As Integer = 12345      Dim MyMachine As String = "brianpc1"      Dim MyEndPoint As String = "TempConverter"      Dim URIString As String      URIString = "tcp://" & MyMachine & ":" & MyPort & "/" & MyEndPoint      'Create the remote object instance      Dim MyRemoteObject As TempConverter.clsTemperature      Dim MyObjType As System.Type = GetType(TempConverter.clsTemperature)      MyRemoteObject = CType(Activator.GetObject(MyObjType, URIString),  TempConverter.clsTemperature)      'Call a method on the remote object      If MyRemoteObject Is Nothing Then          MessageBox.Show("Error!")      Else          If ConversionType.ToUpper = "CTOF" Then              Return MyRemoteObject.CtoF(InputTemp)          Else              Return MyRemoteObject.FtoC(InputTemp)          End If      End If  End Function  Private Sub btnConvertToC_Click(ByVal sender As System.Object, _      ByVal e As System.EventArgs) Handles btnConvertToC.Click      txtTempC.Text = PerformConversion("FTOC", Convert.ToSingle(txtTempF.Text))  End Sub  Private Sub btnConvertToF_Click(ByVal sender As Object, _      ByVal e As System.EventArgs) Handles btnConvertToF.Click      txtTempF.Text = PerformConversion("CTOF", Convert.ToSingle(txtTempC.Text))  End Sub 

Note that in Listing 9.4, a URI string is used that enables the client to find the remote object. A URI, which stands for Uniform Resource Indicator, includes the machine name, channel and port, and endpoint. The URI string from Listing 9.4 looks like this:

 tcp://brianpc1:12345/TempConverter 

The GetObject method of the Activator class is one means of creating a remote object instance. However, this returns the object as a generic value of type Object, so the Ctype function is included to convert the remote reference to the locally defined type clsTemperature.

Testing the Example

Now that you have created the three parts of the distributed application, click the Visual Studio Start button. The two forms from the client and host applications should appear. Click the Start Server button on the host application and wait for the confirmation message box. Next, test the remote functions by converting various temperature values in the client app.

If you have another PC on your network with the .NET Framework installed, move the files ClientApp.exe and TempConverter.dll from your project's bin directory to this machine. As long as the host application is running on the first PC, you should be able to run the client from the second PC. You can run the command NETSTAT from a Command Prompt window to verify a connection between the PCs using port 12345.

In our simple example, we used a reference to TempConverter.dll to provide metadata information to the client application, which means that this DLL would need to be distributed with the client application. However, referencing the class directly during development is just one way to provide this information to the client. Microsoft also recommends the following approaches:

  • Create an interface DLL file that clients use to obtain metadata information. The remote object on the server can implement this interface.

  • Use the SOAPSUDS.EXE tool, which can read a class and build a DLL you can reference from the client application.

Our example is very simple and just scratches the surface of the features of .NET Remoting. For more information on Remoting, please read the very extensive documentation included with the .NET Framework SDK.


    Team-Fly    
    Top
     



    Special Edition Using Visual Basic. NET
    Special Edition Using Visual Basic.NET
    ISBN: 078972572X
    EAN: 2147483647
    Year: 2001
    Pages: 198

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net