Understanding .NET Remoting - Transport Channels (Page 6 of 8 )
Channels provide an abstraction for the actual conduits that will carry the message across the wire. The HTTP Channel, TCP Channel, and SMTP Channels are provided out of the box by the remoting framework. The HTTP Channel is your best bet if you are planning to deploy your server in an Internet environment and the consumers of your services are outside your firewall. Messages sent through the HTTP channel are by default, SOAP payloads. The TCP channel offers better performance than the HTTP channel. It uses a binary payload by default, but it can also carry SOAP payloads if required. If all the consumers of your service are within your own internal network/LAN and inside the firewall, then the TCP channel can be used since it offers better performance using raw sockets with a binary payload. But if you are looking at deploying the remote object across the Internet, that needs to be accessible by clients or consumers outside your firewall, the HTTP channel is the best option.
The SMTP channel also uses a SOAP payload by default. Eventually, it's all matter of deciding on the tradeoffs between performance and interoperability. The good thing about the remoting architecture is that it does not mandate that you have to use a specific formatter with a particular transport channel. So you could use the Binary formatter with the HTTP channel or use the SOAP formatter with the TCP channel. The pluggable channel & serialization formatter architecture allows you to mix'n'match channels with appropriate payloads to suit your needs & requirements.
To write a custom channel, your channel classes would need to implement the IChannelSender and the IChannelReceiver interface. More specifically, each of these interfaces inherits from the IChannel interface. Your IChannelSender interface implementation should take care of client side chores. You will need to create a message sink that dispatches the message to the server object's URN endpoint after serializing it. At the server end, your IChannelReceiver implementation should listen for requests, deserialize the message received, should make the method call on the object, serialize the response and send it back to the client. The message sink created by the ChannelSender object in the client should then read back the response message and deserialize it. The .NET framework SDK ships with a custom channel sample that uses Named Pipes to communicate between the client and the server. So you might want to take a look at that sample to get a better understanding on how you could put together your own custom channel. You'll find this sample under the Remoting samples folder.
Here is a brief summary of what we discussed:
Uses the SOAP serialization formatter by default.
Uses the binary serialization formatter by default.
Suitable for Internet deployment and works well with firewalls.
More suitable for deployment within an internal network/LAN
Performance is fairly good.
Very good performance since it uses raw sockets and a binary payload.
High interoperability. Channel can be used to talk to a large number of services (deployed even in disparate platforms) that can speak SOAP.
Not as interoperable as the HTTP channel.
Lifetime Management & Activation Policies A .NET remote object's host can decide how it wants to manage the object's lifetime and activation policy when it registers the object at the URN endpoint using RemotingServices.RegisterWellKnownType . The lifetime and activation options that are available include SingleCall , Singleton , a n d Client Activated Objects (CAO ).The last parameter in RemotingServices.RegisterWellKnownType takes a WellKnownObjectMode enum value that specifies the mode to use.
SingleCall objects don't maintain any state between calls and every call to the object would be serviced by a new instance of the object. So essentially, they are stateless and are perfect candidates for load balancing and would scale-out well if deployed in a server farm.
Singleton objects follow the classic Singleton pattern where the same instance of the object is used to service requests from consumers. This pattern is useful when you need to maintain shared data or resources between all clients. For example, say you wanted to maintain a hit counter that tracked the number of hits on a server resource.
Client Activated Objects (CAO) use the activation & lifetime pattern that we see in object models like COM. When the client calls new or Activator.CreateInstance to create a CAO object, a remote request is sent in the form of an activation message that is intercepted by the Remoting Activator and the remote object is invoked. An object reference( ObjRef ) is passed back to the client. Every call that the client makes using the ObjRef that was handed over, is serviced by the same object on the server, thus allowing you to maintain state between method calls. This is quite different from the SingleCall and Singleton models because in both those models, the remote object is activated only when the first method call is made on the proxy and not during the actual instance creation.
The procedure for exposing an object as a Client Activated Object (CAO) is slightly different from that of exposing an object as a Singleton or SingleCall object. In the CAO model, we have to indicate the object we are exposing using the Export attribute instead of the WellKnownObject attribute in the remote configuration file that the host will be loading. We already took a look at the WellKnownObject attribute in the remoting.cfg file when we hosted the object in IIS. This attribute needs to be used if you are exposing your object with a Singleton or SingleCall lifetime policy. But if you want to expose the object as a Client Activated Object (CAO) , then you must use the Export attribute and specify the assembly name and the type name of the object that you are exposing as a Client Activated Object.
Here's the configuration file that we would use if we wanted to expose the Diner object as a CAO . In this example, the loaded configuration file contains enough information to tell the host to register a HTTP Channel - so we do not have to register it explicitly from our code.
If you were to consume this object from a client application and were using the configuration file approach, your client could simply use new to instantiate the object after loading the configuration file (like the one shown in listing 7) by calling RemotingServices.ConfigureRemoting.
The example above assumes that the host application (http://localhost:8080/MyDiner) for the remote object is listening in port 8080 after registering a HTTP Channel and has loaded the configuration file shown above in Listing 6.Alternatively, you could also use Activator.CreateInstance in your client to activate the object by specifying the URN of the application hosting the object.
Here's a summary of the various remoting lifetime management/activation policies:
Client Activated Object
Every call to the object creates a new object instance to service the call.
Same object instance is used to service all client requests.
Very similar to the COM programming model. When the client unmarshals an object reference & makes a method call on that reference, it will get serviced by the same object instance in the server, thus allowing you to maintain state between method calls.
Will scale-out well when deployed in a server farm.
Will not scale-out in server farm.
Will not scale-out as well as the SingleCall model.