Section 23.10. .NET Remoting


23.10. .NET Remoting

The .NET framework provides a distributed computing technology called .NET remoting that allows a program to invoke methods of objects located on other computers over a network, rather than communicate with streams of bytes (as demonstrated earlier in this chapter). .NET remoting is similar in concept to RMI (remote method invocation) in Java and RPC (remote procedure call) in procedural programming languages. .NET remoting is also similar to Web services (Chapter 22) with a few key differences. With Web services, a client application communicates with a Web service that is hosted by a Web server. The client and the Web service can be written in any language, as long as they can transmit messages in SOAP. With .NET remoting, a client application communicates with a server application, both of which must be written in .NET languages. Using .NET remoting, a client and a server can communicate via method calls, and objects can be transmitted between applicationsa process known as marshaling the objects.

Channels

The client and the server are able to communicate with one another through channels. Channels typically use either the HTTP protocol or the TCP protocol to transmit messages. The advantage of an HTTP channel is that firewalls usually permit HTTP connections by default, while they normally block unfamiliar TCP connections. The advantage of a TCP channel is better performance than an HTTP channel. In a .NET remoting application, the client and the server each create a channel, and both channels must use the same protocol to communicate with one another. In our example, we use HTTP channels.

Marshaling

There are two ways to marshal an objectby value and by reference. Marshal-by-value requires that the object be serializablethat is, capable of being represented as a formatted message that can be sent between applications through a channel. The receiving end of the channel deserializes the object to obtain a copy of the original object. To enable an object to be serialized and deserialized, its class must be declared with the <Serializable()> attribute or must implement interface ISerializable.

Marshal-by-reference requires that the object's class extend class MarshalByRefObject of namespace System. An object that is marshaled by reference is referred to as a remote object, and its class is referred to as a remote class. When an object is marshaled by reference, the object itself is not transmitted. Instead, two proxy objects are created a transparent proxy and a real proxy. The transparent proxy provides all the Public services of a remote object. Typically, a client calls the methods and properties of the transparent proxy as if it were the remote object. The transparent proxy then calls the Invoke method of the real proxy. This sends the appropriate message from the client channel to the server channel. The server receives this message and performs the specified method call or accesses the specified property on the actual object, which resides on the server. In our example, we marshal a remote object by reference.

Weather Information Application Using .NET Remoting

We now present a .NET remoting example that downloads the Traveler's Forecast weather information from the National Weather Service Web site:

 http://iwin.nws.noaa.gov/iwin/us/traveler.html 


[Note: As we developed this example, the National Weather Service indicated that the information provided on the Traveler's Forecast Web page would be provided via Web services in the near future. The information we use in this example depends directly on the format of the Traveler's Forecast Web page. If you have trouble running this example, please refer to the FAQ page for this book, which is accessible via www.deitel.com/faq.html. This potential problem demonstrates a benefit of using Web services or .NET remoting to implement distributed computing applications that may change in the future. Separating the server part of the application, which depends on the format of an outside data source, from the client part of the application allows the server implementation to be updated without requiring any changes to the client.]

Our .NET remoting application consists of five components:

  1. Serializable class CityWeather, which represents the weather report for one city.

  2. Interface Report, which declares a property Reports that a client application accesses via the marshaled object to obtain a collection of CityWeather objects.

  3. Remote class ReportInfo, which extends class MarshalByRefObject, implements interface Report and will be instantiated only on the server.

  4. A WeatherServer application that sets up a server channel and makes the ReportInfo class available at a particular URI (uniform resource identifier).

  5. A WeatherClient application that sets up a client channel and requests a Report-Info object from the WeatherServer to retrieve the day's weather report.

Class CityWeather

Class CityWeather (Fig. 23.9) contains weather information for one city. Class City-Weather will be published in the Weather.dll class library file that both the server application and the client application must reference. For this reason, you should place this class (and interface Report from Fig. 23.10) in a class library project. Class CityWeather is declared with attribute Serializable (line 4), which indicates that an object of class City-Weather can be marshaled by value. This is necessary because CityWeather objects will be returned by the ReportInfo object's Reports property, and the return values of the methods and properties declared by a remote class must themselves be marshaled by value from the server to the client. (The argument values in method calls will also be marshaled by value from the client to the server.) Thus when the client calls a Get accessor that returns CityWeather objects, the server channel will serialize the CityWeather objects in a message that the client channel can deserialize to create copies of the original CityWeather objects. Class CityWeather also implements interface IComparable (line 5) so that an ArrayList of CityWeather objects can be sorted alphabetically.

Figure 23.9. Class CityWeather.

  1  ' Fig. 23.9: CityWeather.vb  2  ' Class representing the weather information for one  city.  3  4  <Serializable()> _   5  Public Class CityWeather : Implements IComparable  6     Private cityNameValue As String  7     Private descriptionValue As String  8     Private temperatureValue As String  9 10     Public Sub New(ByVal city As String, ByVal information As String, _ 11        ByVal degrees As String) 12 13        cityNameValue = city 14        descriptionValue = information 15        temperatureValue = degrees 16     End Sub ' New 17 18     ' read-only property that gets city's name 19     Public ReadOnly Property CityName() As String 20        Get 21           Return cityNameValue 22        End Get 23     End Property ' CityName 24 25     ' read-only property that gets city's weather description 26     Public ReadOnly Property Description() As String 27        Get 28           Return descriptionValue 29        End Get 30     End Property ' Description 31 32     ' read-only property that gets city's temperature 33     Public ReadOnly Property Temperature() As String 34        Get 35           Return temperatureValue 36        End Get 37     End Property ' Temperature 38 39     ' implementation of CompareTo method for alphabetizing 40     Public Function CompareTo(ByVal obj As Object) _ 41        As Integer Implements System.IComparable.CompareTo 42 43        Return String.Compare(CityName, CType(obj, CityWeather).CityName) 44     End Function ' CompareTo 45 46     ' return string representation of this CityWeather object 47     ' (used to display the weather report on the server console) 48     Public Overrides Function ToString() As String 49        Return CityName     &  " | " & Temperature & " | " & Description 50     End Function ' ToString 51  End Class ' CityWeather 

Figure 23.10. Interface Report in namespace Weather.

 1  ' Fig. 23.10: Report.vb 2  ' Interface that defines a property for getting 3  ' the information in a weather report. 4  Imports System.Collections 5 6  Public Interface Report 7     ReadOnly Property Reports() As ArrayList 8  End Interface ' Report 

CityWeather contains three instance variables (lines 68) for storing the city's name (cityNameValue), the high/low temperature information (temperatureValue) and the description of the weather condition (descriptionValue). The CityWeather constructor (lines 1016) initializes the three instance variables. Lines 1937 declare three read-only properties that allow the values of the three instance variables to be retrieved. CityWeather implements IComparable, so it must declare a method called CompareTo that takes an Object reference and returns an Integer (lines 4044). Also, we want to alphabetize CityWeather objects by their cityNames, so CompareTo calls String method Compare with the cityNames of the two CityWeather objects (line 43). Class CityWeather also overrides the ToString method to display information for this city (lines 4850). Method ToString is used by the server application to display the weather information retrieved from the Traveler's Forecast Web page in the console.

Interface Report

Figure 23.10 shows the code for interface Report. Interface Report also will be included with class CityWeather in the Weather.dll class library file, so it can be used in both the client and server applications. Report declares a read-only property (line 7) that returns an ArrayList of CityWeather objects (ArrayList was introduced in the example in Section 17.8). The client application will use this property to retrieve the information in the weather reporteach city's name, high/low temperature and weather condition.

Class ReportInfo

Remote class ReportInfo (Fig. 23.11) implements interface Report (line 9) of namespace Weather (specified by the Imports statement in line 7). ReportInfo also extends base class MarshalByRefObject. Class ReportInfo is part of the remote WeatherServer application and will not be directly available to the client application.

Figure 23.11. Class ReportInfo, which implements interface Report, is marshaled by reference.

  1  ' Fig. 23.11: ReportInfo.vb  2  ' Class that implements interface Report, retrieves  3  ' and returns data on weather  4  Imports System.Collections  5  Imports System.IO  6  Imports System.Net  7  Imports Weather  8  9  Public Class ReportInfo : Inherits MarshalByRefObject : Implements Report 10    Private cityList As ArrayList ' cities, temperatures, descriptions 11 12    Public Sub New() 13       cityList = New ArrayList() 14 15       ' create WebClient to get access to Web page 16       Dim myClient As New WebClient()              17 18       ' get StreamReader for response so we can read page 19       Dim input As New StreamReader(myClient.OpenRead( _  20       "http://iwin.nws.noaa.gov/iwin/us/traveler.html"))  21 22       ' indicates first batch of cities   23       Dim separator1 As String = "TAV12" 24       ' indicates second batch of cities  25       Dim separator2 As String = "TAV13"  26 27       ' locate separator1 in Web page                                28       While Not input.ReadLine().StartsWith(separator1) ' do nothing 29       End While                                                      30       ReadCities(input) ' read the first batch of cities             31 32       ' locate separator2 in Web page                                33       While Not input.ReadLine().StartsWith(separator2) ' do nothing 34       End While                                                      35       ReadCities(input) ' read the second batch of cities            36 37       cityList.Sort() ' sort list of cities by alphabetical order 38       input.Close() ' close StreamReader to NWS server 39 40       ' display the data on the server side 41       Console.WriteLine("Data from NWS Web site:") 42 43       For Each city As CityWeather In cityList 44          Console.WriteLine(city) 45       Next city ' end foreach 46    End Sub ' New 47 48    ' utility method that reads a batch of cities 49    Private Sub ReadCities( ByVal  input As StreamReader) 50       ' day format and night format 51       Dim dayFormat As String = _                                     52           "CITY              WEA         HI/LO   WEA           HI/LO" 53       Dim nightFormat           As String  = _                        54           "CITY              WEA         LO/HI   WEA           LO/HI" 55       Dim inputLine As String = ""                                    56 57       ' locate header that begins weather information       58       Do                                                    59           inputLine = input.ReadLine()                      60       Loop While Not inputLine.Equals(dayFormat)  And Not _ 61           inputLine.Equals(nightFormat)                     62 63       inputLine = input.ReadLine() ' get first city's data 64 65       ' while there are more cities to read 66        While inputLine.Length > 28 67           ' create CityWeather object for city                         68           Dim weather As New CityWeather(inputLine.Substring(0, 16), _ 69              inputLine.Substring(16, 7), inputLine.Substring(23, 7))   70 71           cityList.Add(weather) ' add to ArrayList            72           inputLine = input.ReadLine() ' get next city's data 73        End While ' end while 74     End Sub ' ReadCities 75 76     ' property for getting the cities' weather reports 77     Public ReadOnly Property Reports() As _                           78        System.Collections.ArrayList Implements Weather.Report.Reports 79 80        Get 81           Return cityList 82        End Get 83     End Property ' Reports 84  End Class ' ReportInfo 

Lines 1246 declare the ReportInfo constructor. Line 16 creates a WebClient (namespace System.Net) object to interact with a data source that is specified by a URL in this case, the URL for the NWS Traveler's Forecast page (http://iwin.nws.noaa.gov/iwin/us/traveler.html). Lines 1920 call WebClient method OpenRead, which returns a Stream that the program can use to read data containing the weather information from the specified URL. This Stream is used to create a StreamReader object so that the program can read the Web page's HTML markup line-by-line.

The section of the Web page in which we are interested consists of two batches of citiesAlbany through Reno, and Salt Lake City through Washington, D.C. The first batch occurs in a section that starts with the string "TAV12" while the second batch occurs in a section that starts with the string "TAV13". We declare variables separator1 and separator2 to store these strings. Lines 2829 read the HTML markup one line at a time until "TAV12" is encountered. Then the program calls utility method ReadCities to read a batch of cities into ArrayList cityList. Next, lines 3334 read the HTML markup one line at a time until "TAV13" is encountered, and line 35 makes another call to method ReadCities to read the second batch of cities. Line 37 calls method Sort of class ArrayList to sort the CityWeather objects into alphabetical order by city name. Line 38 closes the StreamReader connection to the Web site. Lines 4345 output the weather information for each city to the server application's console display.

Lines 4974 declare utility method ReadCities, which takes a StreamReader object and reads the information for each city, creates a CityWeather object for it and places the CityWeather object in cityList. The loop in lines 5861 continues to read the page one line at a time until it finds the header line that begins the weather forecast table. This line starts with either dayFormat (lines 5152), indicating the header for the daytime information, or nightFormat (lines 5354), indicating the header for the nighttime information. Because the line could be in either format based on the time of day, the loop-continuation condition checks for both (lines 6061). Line 59 reads the next line from the Web page, which is the first line containing temperature information.

The loop in lines 6673 creates a new CityWeather object to represent the current city. It parses the string containing the current weather data, separating the city name, the weather condition and the temperature. The CityWeather object is added to cityList. Then the next line from the page is read and stored in inputLine for the next iteration. This process continues while the length of the string read from the Web page is greater than 28 (the lines containing weather data are all longer than 28 characters). The first line shorter than this signals the end of that forecast section in the Web page.

Read-only property Reports (lines 7783) implements the Report interface's Reports property to return cityList. The client application will remotely call this property to retrieve the day's weather report.

Class WeatherServer

Figure 23.12 contains the server code. The Imports statements in lines 46 specify .NET remoting namespaces System.Runtime.Remoting, System.Runtime.Remoting.Channels and System.Runtime.Remoting.Channels.Http. The first two namespaces are required for .NET remoting, and the third is required for HTTP channels. Namespace System.Runtime.Remoting.Channels.Http requires the project to reference the System.Runtime.Remoting assembly, which can be found under the .NET tab in the Add References menu. The Imports statement at line 7 specifies namespace Weather, which contains interface Report. Remember to add a reference to Weather.dll in this project.

Figure 23.12. Class WeatherServer exposes remote class ReportInfo.

  1  ' Fig. 23.12: WeatherServer.cs  2  ' Server application that uses .NET remoting to send  3  ' weather report information to a client  4  Imports System.Runtime.Remoting                5  Imports System.Runtime.Remoting.Channels       6  Imports System.Runtime.Remoting.Channels.Http  7  Imports Weather                                8  9  Module WeatherServer 10     Sub Main() 11        ' establish HTTP channel                         12        Dim channel As New HttpChannel(50000)            13        ChannelServices.RegisterChannel(channel, False ) 14 15        ' register ReportInfo class                                    16        RemotingConfiguration.RegisterWellKnownServiceType( _          17        GetType(ReportInfo), "Report" , WellKnownObjectMode.Singleton) 18 19        Console.WriteLine("Press Enter to terminate server.") 20        Console.ReadLine() 21     End Sub ' Main 22  End Module ' WeatherServer 

Lines 1213 in Main register an HTTP channel on the current machine at port 50000the port number that clients will use to connect to the WeatherServer remotely. The argument False in line 13 indicates that we do not wish to enable security, which is beyond the scope of this introduction. Lines 1617 register the ReportInfo class type at the "Report" URI as a Singleton remote class. If a remote class is registered as Singleton, only one remote object will be created when the first client requests that remote class, and that remote object will service all clients. The alternative mode is SingleCall, where one remote object is created for each individual remote method call to the remote class. [Note: A Singleton remote object will be garbage collected after being idle for 5 minutes. A new Singleton remote object will be created by the server if another client requests one later. The article msdn.microsoft.com/msdnmag/issues/03/12/LeaseManager/default.aspx provides more information on the lifetime of remote objects.] The ReportInfo remote class is now available to clients at the URI "http://IPAddress :50000/Report" where IPAddress is the IP address of the computer on which the server is running. The channel remains open as long as the server application continues running, so line 20 waits for the user running the server application to press Enter before terminating the application.

Class FrmWeatherClient

FrmWeatherClient (Fig. 23.13) is a Windows application that uses .NET remoting to retrieve weather information from the WeatherServer and displays the information in a graphical, easy-to-read manner. The GUI contains 43 Labelseach displays the weather information for one city in the Traveler's Forecast. The Labels are placed in a Panel with a vertical scroll bar. Lines 57 are Imports statements for the namespaces that are required to perform .NET remoting. For this project, you must add references to the assembly System.Runtime.Remoting and the Weather.dll file we created earlier.

Figure 23.13. Class WeatherClient accesses a ReportInfo object remotely and displays the weather report.

  1  ' Fig. 23.13: WeatherClient.vb  2  ' Client that uses .NET remoting to retrieve a weather report.  3  Imports System.Collections                     4  Imports System.Drawing                         5  Imports System.Runtime.Remoting                6  Imports System.Runtime.Remoting.Channels       7  Imports System.Runtime.Remoting.Channels.Http  8  Imports Weather                                9 10  Public Class FrmWeatherClient 11     ' retrieve weather data 12     Private Sub FrmWeatherClient_Load(ByVal sender As System.Object, _ 13        ByVal e As System.EventArgs) Handles MyBase.Load 14        ' setup HTTP channel, does not need to provide a port number 15        Dim channel As New HttpChannel()                             16        ChannelServices.RegisterChannel(channel, False)             17 18        ' obtain a proxy for an object that implements interface Report 19        Dim info As Report = CType(RemotingServices.Connect( _          20        GetType(Report), "http://localhost:50000/Report" ), Report)     21 22        ' retrieve an ArrayList of CityWeather objects 23        Dim cities As ArrayList = info.Reports         24 25        ' create array and populate it with every Label 26        Dim cityLabels(43) As Label                     27        Dim labelCounter As Integer = 0 28 29        Dim control As Control 30        For Each control In pnlDisplay.Controls 31           If TypeOf control Is Label Then 32              cityLabels(labelCounter) = CType(control, Label) 33              labelCounter += 1 ' increment Label counter 34           End If 35        Next control 36 37        ' create Hashtable and populate with all weather conditions 38        Dim weather As New Hashtable()                              39        weather.Add("SUNNY" , "sunny") 40        weather.Add("PTCLDY" , "pcloudy") 41        weather.Add("CLOUDY" , "mcloudy") 42        weather.Add("MOCLDY" , "mcloudy") 43        weather.Add("VRYCLD" , "mcloudy") 44        weather.Add("TSTRMS" , "rain") 45        weather.Add("RAIN" , "rain") 46        weather.Add("FZRAIN" , "rain") 47        weather.Add("SNOW" , "snow") 48        weather.Add("VRYHOT" , "vryhot") 49        weather.Add("FAIR" , "fair") 50        weather.Add("RNSNOW" , "rnsnow") 51        weather.Add("SHWRS" , "showers") 52        weather.Add("WINDY" , "windy") 53        weather.Add("NOINFO" , "noinfo") 54        weather.Add("MISG" , "noinfo") 55        weather.Add("DRZL" , "rain") 56        weather.Add("HAZE" , "noinfo") 57        weather.Add("SMOKE" , "mcloudy") 58        weather.Add("SNOSHW" , "snow") 59        weather.Add("FLRRYS" , "snow") 60        weather.Add("FOG" , "noinfo") 61 62        ' create the font for the text output                     63        Dim font As New Font( "Courier New" , 8 , FontStyle.Bold) 64 65        ' for every city 66        For i As Integer = 0 To cities.Count - 1 67           ' use array cityLabels to find the next Label 68           Dim currentCity As Label = cityLabels(i)      69 70           ' use ArrayList cities to find the next CityWeather object 71           Dim city As CityWeather = CType(cities(i), CityWeather)    72 73           ' set current Label's image to image                         74           ' corresponding to the city's weather condition -          75           ' find correct image name in Hashtable weather               76           currentCity.Image = New Bitmap("images\" & _                 77           weather(city.Description.Trim()).ToString() & ".png")        78           currentCity.Font = font ' set font of Label                  79           currentCity.ForeColor = Color.White ' set text color of Label 80 81           ' set Label's text to city name and temperature    82           currentCity.Text = _                               83              vbCrLf & " " & city.CityName & city.Temperature 84        Next 85     End Sub ' FrmWeatherClient_Load 86  End Class ' FrmWeatherClient 

Method FrmWeatherClient_Load (lines 1285) retrieves the weather information when this Windows application loads. Line 15 creates an HTTP channel without specifying a port number. This causes the HttpChannel constructor to choose any available port number on the client computer. A specific port number is not necessary because this application does not have its own clients that need to know the port number in advance. Line 16 registers the channel on the client computer. This will allow the server to send information back to the client. Lines 1920 declare a Report variable and assign to it a proxy for a Report object instantiated by the server. This proxy allows the client to remotely call ReportInfo's properties by redirecting method calls to the server. RemotingServices method Connect connects to the server and returns a reference to the proxy for the Report object. For testing purposes, we execute the client and the server on the same computer, so we use localhost in the URL that represents the server application. To connect to a WeatherServer on a different computer, you must replace localhost with the name or IP address of the server computer. Line 23 retrieves the ArrayList of City-Weather objects generated by the ReportInfo constructor (lines 1246 of Fig. 23.11). Variable cities now refers to an ArrayList of CityWeather objects that contains the information taken from the Traveler's Forecast Web page.

Because the application presents weather data for so many cities, we must establish a way to organize the information in the Labels and to ensure that each weather description is accompanied by an appropriate image. The program uses an array to store all the Labels, and a Hashtable (discussed further in Chapter 27, Collections) to store weather descriptions and the names of their corresponding images. A Hashtable stores keyvalue pairs, in which both the key and the value can be any type of object. Method Add adds keyvalue pairs to a Hashtable. The class also provides an indexer to return the values for particular keys in the Hashtable. Line 26 creates an array of Label references, and lines 3035 place the Labels we created in the IDE's Form designer in the array so that they can be accessed programmatically to display weather information for individual cities. Line 38 creates Hashtable object weather to store pairs of weather conditions and the names for images associated with those conditions. Note that a given weather-description name does not necessarily correspond to the name of the PNG file containing the correct image. For example, both "TSTRMS" and "RAIN" weather conditions use the rain.png image file.

Lines 6684 set each Label so that it contains a city name, the current temperature in the city and an image corresponding to the weather conditions for that city. Line 68 retrieves the Label that will display the weather information for the next city. Line 71 uses ArrayList cities to retrieve the CityWeather object that contains the weather information for the city. Lines 7677 set the Label's image to the PNG image that corresponds to the city's weather conditions. This is done by eliminating any spaces in the description string by calling String method trim and retrieving the name of the PNG image from the weather Hashtable. Lines 7879 set Label's Font property to the Font object created at line 63, and the ForeColor property to white for readability against the black and blue background image on the Label. Lines 8283 set the Text property to display the city's name and high/low temperatures. [Note: To preserve the layout of the client application's window, we set the MaximumSize and MinimumSize properties of the Windows Form to the same value so that the user cannot resize the window.]

Web Resources for .NET Remoting

This section provided a basic introduction to .NET remoting. There is much more to this powerful .NET framework capability. The following Web sites provide additional information. Searching for ".NET remoting" with most search engines yields many additional resources.

msdn.microsoft.com/library/en-us/cpguide/html/cpconaccessingobjectsinotherapplicationdomainsusingnetremoting.asp

The .NET Framework Developer's Guide on the MSDN Web site provides detailed information on .NET remoting, including articles that include choosing between ASP.NET and .NET remoting, an overview of .NET remoting, advanced .NET remoting techniques and .NET remoting examples.

msdn.microsoft.com/library/en-us/dndotnet/html/introremoting.asp

Offers a general overview of .NET remoting capabilties.

search.microsoft.com/search/results.aspx?qu=.net+remoting

Provides links to many .NET remoting articles and resources.



Visual BasicR 2005 for Programmers. DeitelR Developer Series
Visual Basic 2005 for Programmers (2nd Edition)
ISBN: 013225140X
EAN: 2147483647
Year: 2004
Pages: 435

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