- Introduction
- Application Boundaries
- Distributed Applications
- .NET Remoting Architecture
- Applying .NET Remoting
- Chapter Summary
- Apply Your Knowledge
.NET Remoting Architecture
.NET remoting enables objects in different application domains to talk to each other. The real strength of remoting is in enabling communication between objects when their application domains are separated across the network. In this case, remoting transparently handles details related to network communication.
Before getting into details, let's first answer a basic questionHow can remoting establish cross-application domain communication when an application domain does not allow direct calls across its boundary?
Remoting takes an indirect approach to application domain communication by creating proxy objects as shown in Figure 3.1. Both application domains communicate with each other using the following steps:
When a client object wants to create an instance of the server object, the remoting system at the client side instead creates a proxy of the server object. The proxy object lives at the client but behaves just like the remote object; this leaves the client with the impression that the server object is in the client's process.
Figure 3.1 In this simplified view of .NET remoting, note that the client and server communicate indirectly through a proxy object.
-
When the client object calls a method on the server object, the proxy passes the call information to the remoting system on the client. This remoting system in turn sends the call over the channel to the remoting system on the server.
-
The remoting system on the server receives the call information and, on the basis of it, invokes the method on the actual object on the server (creating the object if necessary).
-
The remoting system on the server collects all the results of the method invocation and passes them through the channel to the remoting system on the client.
-
The remoting system at the client receives the response of the server and returns the results to the client object through the proxy.
The process of packaging and sending method calls among the objects across the application boundaries via serialization and deserialization, as shown in the preceding steps, is also known as marshalling.
Now that you have a basic idea of how .NET remoting works, its time to get into details. In the next few sections, I'll explain the various key components and terminology of .NET remoting.
Object Marshalling
Remotable objects are objects that can be marshalled across the application domains. In contrast, all other objects are known as non-remotable objects. There are two types of remotable objects:
Marshal-by-value (MBV) ObjectsThese objects are copied and passed out of the server application domain to the client application domain.
Marshal-by-reference (MBR) ObjectsThese objects are accessed on the client side using a proxy. The client just holds a reference to these objects.
Marshal-by-Value Objects
MBV objects reside on the server. However, when the client invokes a method on the MBV object, the MBV object is serialized, transferred over the network, and restored on the client as an exact copy of the server-side object. The method is then invoked directly on the client. When this happens, the MBV object is no longer a remote object. Any method calls to the object do not require any proxy object or marshalling because the object is locally available.
The MBV objects can provide faster performance by reducing the number of network roundtrips, but in the case of large objects, the time taken to transfer the serialized object from the server to the client can be very significant. Further, MBV objects do not allow you the flexibility to run the remote object in the server environment.
A MBV object can be created by declaring a class with the Serializable attribute; for example
' Define a MBV remoting object <Serializable()> Public Class MyMBVObject ' Implementation details End Class
If a class needs to control its own serialization, it can do so by implementing the ISerializable interface as shown here:
Imports System.Runtime.Serialization ' Define a MBV remoting object <Serializable()> Public Class MyMBVObject Implements ISerializable ' Class details ... 'Implement custom serialization here Public Sub GetObjectData( _ ByVal info As SerializationInfo, _ ByVal context As StreamingContext) ' Serialization details ... End Sub End Class
Marshal-by-Reference Objects
MBR objects are remote objects. They always reside on the server, and all methods invoked on these objects are executed at the server side. The client communicates with the MBR object on the server using a local proxy object that holds the reference to the MBR object.
Although the use of MBR objects increases the number of network roundtrips, they are a good choice when the objects are prohibitively large or when the functionality of the object is only available in the server environment on which it is created.
An MBR object can be created by deriving from the System.MarshalByRefObject class; for example,
' Define a MBR remoting object Public Class MyMBRObject Inherits MarshalByRefObject ' Class details ... End Class
Channels
Create and consume a .NET Remoting object: Select a channel protocol and a formatter. Channel protocols include TCP and HTTP. Formatters include SOAP and binary.
Channels are the objects that transport messages across remoting boundaries such as application domains, processes, and computers. When a client calls a method on a remote object, the details of the method call are transported to the remote object through a channel. Any results returned from the remote object are communicated back to the client again through the same channel.
The .NET remoting framework ensures that before a remote object can be called, it has registered at least one channel with the remoting system on the server. Similarly, the client object should specify a channel before it can communicate with a remote object. If the remote object offers more than one channel, the client can connect using the channel that best suits its requirements.
A channel has two endpoints. The channel object at the receiving end of a channel (the server) listens to a particular protocol using the specified port number, whereas the channel object at the sending end of the channel (the client) sends information to the receiving end using the protocol and port number specified by the channel object on the receiving end.
TIP
Port Numbers Should Be Unique on a Machine Each channel is uniquely associated with a TCP/IP port number. Ports are machine-wide resources; therefore, you cannot register a channel that listens on a port number already in use by some other channel on the same machine.
To participate in the .NET remoting framework, the channel object at the receiving end must implement the IChannelReceiver interface while the channel object at the sending end must implement the IChannelSender interface.
The .NET Framework provides implementations for HTTP (Hypertext Transfer Protocol) and TCP (Transmission Control Protocol) channels. If you want to use a different protocol, you can define your own channel by implementing the IChannelReceiver and IChannelSender interfaces.
HTTP Channels
HTTP channels use HTTP for establishing communication between the two ends. These channels are implemented through the classes of the System.Runtime.Remoting.Channels.Http namespace, as shown in Table 3.1.
Table 3.1 The HTTP Channel Classes
Class |
Implements |
Purpose |
HttpServerChannel |
IChannelReceiver |
An implementation for a server channel that uses the HTTP protocol to receive messages |
HttpClientChannel |
IChannelSender |
An implementation for a client channel that uses the HTTP protocol to send messages |
HttpChannel |
IchannelReceiver IChannelSender |
An implementation of a combined and channel that provides the functionality of both the HttpServerChannel and the HttpClientChannel classes |
The following code example shows how to register a sender-receiver HTTP channel on port 1234:
Imports System Imports System.Runtime.Remoting.Channels Imports System.Runtime.Remoting.Channels.Http ' ... Dim channel As HttpChannel = New HttpChannel(1234) ChannelServices.RegisterChannel(channel) ' ...
The ChannelServices class used in the code provides various remoting-related services. One of its static methods is RegisterChannel(), which helps in registering a channel with the remoting framework.
TCP Channels
A TCP channel uses TCP for establishing communication between the two ends. The TCP channel is implemented through various classes of the System.Runtime.Remoting.Channels.Tcp namespace, as shown in Table 3.2.
Table 3.2 The TCP Channel Classes
Class |
Implements |
Purpose |
TcpServerChannel |
IChannelReceiver |
An implementation for a server channel that uses the TCP protocol to receive messages |
TcpClientChannel |
IChannelSender |
An implementation for a client channel that uses the TCP protocol to send messages |
TcpChannel |
IchannelReceiver IChannelSender |
An implementation of a combined and channel that provides the functionality for both the TcpServerChannel and TcpClientChannel classes |
The following code example shows how to register a sender-receiver TCP channel on port 1234:
Imports System Imports System.Runtime.Remoting.Channels Imports System.Runtime.Remoting.Channels.Tcp ' ... Dim channel As TcpChannel = New TcpChannel(1234) ChannelServices.RegisterChannel(channel) ' ...
TIP
Support for Security .NET remoting has no built-in support for security. It instead depends on the remoting hosts to provide security. The only built-in remoting host that provides security for remote objects is IIS. Therefore, any secured objects must be hosted in IIS unless you write your own security system.
Choosing Between the HTTP and the TCP Channels
Table 3.3 helps you make a decision about which channel to use in a given scenario. In summary, you'll normally limit the use of TCP channel to within a low-risk intranet. For more wide-reaching applications, using HTTP channel makes more sense unless the application's efficiency requirements justifies the cost of creating a customized security system.
Table 3.3 Choosing Between HTTP Channel and TCP Channel
Channel |
Scope |
Efficiency |
Security |
HttpChannel |
Wide, HTTP channel allows you to host objects in a robust HTTP server such as IIS. HTTP channels can be used over the Internet because Integrated firewalls do not generally block HTTP communication. |
Less, because HTTP is a bulky protocol and has a lot of extra overhead. |
More, because when remote objects are hosted in IIS, the HttpChannel can immediately take advantage of Secure Sockets Layer (SSL), Windows Authentication, or Kerberos. |
TcpChannel |
Narrow, Using TCP channel over the Internet would require certain ports in the firewall and could lead to security breaches. |
More, because TCP uses raw sockets to transmit data across the network. |
Less, until you implement a custom security system using the classes provided in the System.Security namespace. |
Formatters
Formatters are the objects used to encode and serialize data into messages before they are transmitted over a channel.
To participate in the .NET remoting framework, a formatter class must implement the IFormatter interface. The .NET Framework packages two formatter classes for common scenariosthe BinaryFormatter class and the SoapFormatter class. If you want to use a different formatter, you can define your own formatter class by implementing the IFormatter interface.
The SOAP Formatter
SOAP (Simple Object Access Protocol) is a relatively straightforward, XML-based protocol for exchanging types and messages between applications. SOAP is an extensible and modular protocol; it is not bound to a particular transport mechanism such as HTTP or TCP.
The SOAP formatter is implemented in the SoapFormatter class of the System.Runtime.Serialization.Formatters.Soap namespace.
SOAP formatting is an ideal way of communicating between applications that use incompatible architectures. However, SOAP is very verbose. SOAP messages require more bytes to represent data than the equivalent binary messages.
The Binary Formatter
Unlike SOAP, the binary format used by the .NET Framework is proprietary and can be understood only within .NET applications. However, as compared to SOAP, the binary format of representing messages is very compact and efficient.
The binary formatter is implemented in the BinaryFormatter class of the System.Runtime.Serialization.Formatters.Binary namespace.
Channels and Formatters
The HTTP channel uses the SOAP formatter as its default formatter to transport messages to and from the remote objects. The HTTP channel uses SoapClientFormatterSinkProvider and SoapServerFormatterSinkProvider classes to serialize and deserialize messages using SoapFormatter. You can create industry-standard XML Web services by using the SOAP formatter with the HTTP channel.
The TCP channel uses the binary format by default to transport messages to and from the remote object. The TCP channel uses BinaryClientFormatterSinkProvider and BinaryServerFormatterSinkProvider classes to serialize and deserialize messages using BinaryFormatter.
However, channels are configurable. You can configure the HTTP channel to use the binary formatter or a custom formatter instead of the SOAP formatter. Similarly, the TCP channel can be configured to use the SOAP formatter or a custom formatter instead of the binary formatter.
Figure 3.2 compares the various combinations of channels and formatters on the scale of efficiency and compatibility. The protocols at the top of the list are the most efficient, while those at the bottom of the list are most interoperable. You can use this information to decide which combination of channel and formatter you would choose in a given scenario.
Figure 3.2 TCP channel with binary formatter provides maximum efficiency whereas HTTP channel with SOAP formatter provides maximum interoperability.
REVIEW BREAK
.NET remoting enables objects in different application domains to talk to each other even when they are separated by applications, computers, or the network.
The process of packaging and sending method calls among objects across the application boundaries via serialization and deserialization is called marshalling.
Marshal-by-value (MBV) and Marshal-by-reference (MBR) are the two types of remotable objects. MBV objects are copied to the client application domain from the server application domain, whereas only a reference to the MBR objects is maintained in the client application domain. A proxy object is created at the client side to interact with the MBR objects.
A channel is an object that transports messages across remoting boundaries such as application domains, processes, and computers. The .NET Framework provides implementations for HTTP and TCP channels to enable communication of messages over the HTTP and TCP protocols, respectively.
A channel has two endpoints. A channel at the receiving end, the server, listens for messages at a specified port number from a specific protocol; and a channel object at the sending end, the client, sends messages through the specified protocol at the specified port number.
Formatters are the objects used to serialize and deserialize data into messages before they are transmitted over a channel. You can format messages in SOAP or the binary format with the help of the SoapFormatter and BinaryFormatter classes in the FCL.
The default formatter to transport messages to and from the remote objects for the HTTP channel is the SOAP formatter and for the TCP channel is the binary formatter.
Remote Object Activation
Between the two types of objects that you have seen (MBV objects and MBR objects), only MBR objects can be activated remotely. No remote activation is needed in the case of MBV objects because the MBV object itself is transferred to the client side.
TIP
Remotable Members An MBR object can remote the following types of members:
Non-static public methods
-
Non-static public properties
-
Non-static public fields
Based on the activation mode, an MBR object is classified into one of the following two categories:
Server-activated objects
Client-activated objects
Server-Activated Objects
Server-activated objects (SAO) are those remote objects whose lifetime is directly controlled by the server.
When a client requests an instance of a server-activated object, a proxy to the remote object is created in the client's application domain. The remote object is only instantiated (or activated) on the server when the client calls a method on the proxy object.
Server-activated objects provide limited flexibility because they can only be instantiated using their default (parameter-less) constructors.
NOTE
Well-Known Objects Remote objects activated in SingleCall or Singleton activation mode are also known as well-known objects.
There are two possible activation modes for a server-activated object:
SingleCall activation mode
Singleton activation mode
SingleCall Activation Mode
In the SingleCall activation mode, an object is instantiated for the sole purpose of responding to just one client request. After the request is fulfilled, the .NET remoting framework deletes the object and reclaims its memory.
Objects activated in the SingleCall mode are also known as stateless because the objects are created and destroyed with each client request; therefore, they do not maintain state across requests. This behavior of SingleCall mode allows for greater server scalability as an object consumes server resources only for a small period, therefore allowing the server to allocate resources to other objects.
The SingleCall activation mode is a desired solution when
The overhead of creating an object is not significant.
The object is not required to maintain its state.
The server needs to support a large number of requests for the object.
The object needs to be supported in a load-balanced environment.
TIP
Load-Balancing and SingleCall Activation Sometimes to improve the overall efficiency of an application, it might be hosted on multiple servers that share the incoming requests to the application. In this case, a request can go to any of the available servers for processing. This scenario is called a load-balancing environment.
Because the SingleCall objects are stateless, it does not matter which server processes requests for such objects. For this reason, SingleCall activation is ideally suited for load-balanced environments.
Common scenarios of the SingleCall activation mode are those applications in which the object is required by the client to do a small amount of work and then the object is no longer required. Some common examples are retrieving the inventory level for an item, displaying tracking information for a shipment, and so on.
Singleton Activation Mode
In the Singleton activation mode, at most there will be one instance of the remote object regardless of the number of clients accessing it.
A Singleton-mode object can maintain state information across method calls. For this reason, such objects are also sometimes known as stateful objects. The state maintained by the Singleton-mode object is globally shared by all of its clients. This generally means that you should not store any state in Singleton-mode objects. But there are circumstances (such as keeping track of usage statistics) in which it can make sense to store shared state.
A Singleton object does not exist on the server forever. Its lifetime is determined by the lifetime lease of the object. I'll discuss lifetime leases later in the chapter.
A Singleton object is a desired solution when
The overhead of creating an object is substantial.
The object is required to maintain its state over a prolonged period.
Several clients need to work on the shared state.
Singleton activation mode is useful in scenarios such as in a chat server in which multiple clients talk to the same remote object and share data between one another through this object.
Client-Activated Objects
Client-activated objects (CAO) are those remote objects whose lifetime is directly controlled by the client. This is in direct contrast with SAOs, where the server, not the client, has the complete control over the lifetime of the objects.
Client-activated objects are instantiated on the server as soon as the client requests the object to be created. Unlike an SAO, a CAO does not delay the object creation until the first method is called on the object.
A CAO can be created using any of the available constructors for the class. A typical CAO activation involves the following steps:
When the client attempts to create an instance of the server object, an activation request message is sent to the remote server.
The server then creates an instance of the requested class using the specified constructor and returns an ObjRef object to the client application that invoked it. The ObjRef object contains all the required information to generate a proxy object that is capable of communicating with a remote object.
The client uses the ObjRef object to create a proxy for the server object on the client side.
An instance of a CAO serves only the client responsible for its creation, and the CAO doesn't get discarded with each request. For this reason, a CAO can maintain state with each client that it is serving, but unlike the Singleton SAO, different CAOs cannot share a common state.
The lifetime of a CAO is determined using lifetime leases. I'll talk more about this topic shortly in a section titled "Lifetime Leases."
A CAO is a desired solution when
The clients want to maintain a private session with the remote object.
The clients want to have more control over how the objects are created and how long they will live.
A CAO is useful in scenarios such as entering a complex purchase order in which multiple roundtrips are involved and clients want to maintain their own private state with the remote object.
Comparing the Object Activation Techniques
Based on the discussions in the previous section, the various object activation techniques can be compared as shown in Figure 3.3.
The SingleCall server activation has maximum scalability because such objects occupy server resources for the minimum amount of the time. This enables the server to allocate its resources between a large numbers of clients.
On the other hand, the client activation of remote objects offers maximum flexibility because you have complete control over the construction and lifetime of the remote object.
Figure 3.3 The SingleCall server activation offers maximum scalability, whereas the client activation offers maximum flexibility.
Lifetime Leases
A lifetime lease is the period of time that a particular object can be active in memory before the .NET framework deletes it and reclaims its memory. Both Singleton SAO and CAO use lifetime leases to determine how long they should continue to exist.
TIP
Leases and Activation Mode Leases apply only to Singleton and Client Activated objects. In the SingleCall activation mode, objects are created and destroyed with each method call.
A lifetime lease is represented using an object that implements the ILease interface defined in the System.Runtime.Remoting.Lifetime namespace. Some of the important members of this interface are listed in Table 3.4.
Table 3.4 Important Members of the ILease Interface
Member Name |
Type |
Description |
CurrentLeaseTime |
Property |
Returns the amount of time remaining on the lease as a TimeSpan object. |
InitialLeaseTime |
Property |
Lets you supply a TimeSpan that dictates the default lifetime of the object. If the object does not receive any method calls, it will only live for this period. |
Register() |
Method |
Specifies an object to be notified when a lease needs to be renewed. |
Renew() |
Method |
Renews a lease for the specified TimeSpan. |
RenewOnCallTime |
Property |
Each time the remote object is called, the lease is renewed for this much time. |
SponsorshipTimeout |
Property |
Specifies the amount of time to wait for a sponsor object to respond to a renewal request. |
TIP
Custom and Infinite Lifetimes A remote object can choose to have a custom defined lifetime by overriding the InitializeLifetimeService() method of the base class, MarshalByRefObject. If the InitializeLifetimeService() method returns a null value, the type tells the .NET Remoting system that its instances are intended to have an infinite lifetime.
Simply speaking, the lease works as follows:
-
When an object is created, its lifetime lease (CurrentLeaseTime) is set using the value of the InitialLeaseTime property (which is 5 minutes by default).
-
Whenever the object receives a call, its CurrentLeaseTime is reset to the time specified by the value of the RenewOnCallTime property (which is 2 minutes by default).
-
The client can also renew a lease for a remote object by directly calling the ILease.Renew() method:
-
When the value of CurrentLeaseTime reaches 0, the .NET Framework contacts any sponsors registered with the lease to check if they are ready to sponsor renewing the object's lease.
-
If the sponsor does not renew the object or the server cannot contact the sponsor within the duration specified by the SponsorshipTimeout property, the object is marked for garbage collection.
Dim lease As ILease = _ CType(RemotingServices. _ GetLifetimeService(RemoteObject), ILease) Dim expireTime As TimeSpan = _ lease.Renew(TimeSpan.FromSeconds(60))
Sponsors are the objects responsible for dynamically renewing the lease of an object in case of its lease expiry. For more information about sponsors, refer to the "Renewing Leases" topic in the .NET Framework Developer's Guide.
REVIEW BREAK
MBR remotable objects can be activated in two modes: Server-activated mode and Client-activated mode.
Server-activated objects (SAO) are those remote objects whose lifetime is directly controlled by the server.
You can activate SAOs in two ways: SingleCall (object is created for each client request) and Singleton (object is created once on the server and is shared by all clients).
The SingleCall activation mode provides the maximum scalability because it does not maintain any state and the object lives for the shortest duration possible.
CAO are created for each client when the client requests to create a remote object. These objects maintain state for each client with which they are associated.
The leased-based lifetime process determines how long the Singleton SAO and CAO should exist.