Channels

One of the first actions performed by both the client and the server is to create an instance of HttpChannel. Here is the server-side statement:

HttpChannel x_channel = new HttpChannel(20172);

Channels are the mechanism used to transport messages between distributed applications. Channels don’t handle the transmission directly, but they act as a binding between a URL scheme and the means by which a remoting operation can be serialized and transmitted.

Channels are defined by three interfaces contained in the System.Runtime.Remoting.Channels namespace:

  • IChannel defines the basis for channels and is used to define common properties.

  • IChannelSender denotes a channel that is capable of emitting a message.

  • IChannelReceiver denotes a channel that will listen for messages of a specific protocol on a specific port.

The .NET Framework provides two bidirectional channel implementations:

  • System.Runtime.Remoting.Channels.Http.HttpChannel

  • System.Runtime.Remoting.Channels.Tcp.TcpChannel

HttpChannel sends messages over HTTP, while TcpChannel sends messages using TCP sockets. By default, the HttpChannel class encodes messages using Simple Object Access Protocol (SOAP), whereas the TcpChannel class uses a binary stream. In most cases, TcpChannel offers better performance because encoding and decoding SOAP messages can be a time-consuming process. On the other hand, SOAP forms the basis for XML Web services and allows clients and servers on different platforms written in different languages to communicate seamlessly.

Both the HttpChannel and TcpChannel classes are convenience wrappers around unidirectional channels; HttpChannel combines HttpServerChannel and HttpClientChannel; TcpChannel combines TcpServerChannel and TcpClientChannel.

Caution

Although HttpChannel and TcpChannel both rely on TCP/IP for communication, messages sent from one kind of channel cannot be processed by the other because TcpChannel uses binary and HttpChannel uses text. It’s important to ensure that messages are sent and received by the same type of channel.

Creating a Channel

Both HttpChannel and TcpChannel offer the same overloaded constructors as detailed in Table 15-2.

Table 15-2. Channel Constructors

Constructor

Description

HttpChannel()

Creates a channel using default values.

TcpChannel()

Locates an available port and binds to it.

 

Creates only a client-side channel (that is, this channel cannot be used to publish remoting services).

HttpChannel(int)

Creates a channel that binds to the specified port number.

TcpChannel(int)

 
 

Creates a channel that can be used to initiate client requests and publish object services. Using 0 (zero) as a port number allows the channel to select an unused port at random and bind to it.

HttpChannel(IDictionary, IClientChannelSinkProvider, IServerChannelSinkProvider)

Creates a channel that is configured by the entries in IDictionary and that uses the specified sinks for processing outbound and inbound messages.

TcpChannel(IDictionary, IClientChannelSinkProvider, IServerChannelSinkProvider)

If either of the sink provider arguments is set to null, the default providers will be used instead.

Using the default constructor creates a channel that is suitable only for remoting clients. Requests can be initiated through the channel, but services cannot be published. If a channel is created with any other constructor, it is able to initiate client requests as well as listen for inbound messages, allowing an application to publish a service for clients and consume services from elsewhere.

The last constructor in the list allows for the greatest control over the channel. Setting aside the sink provider, which is outside the scope of this book, the properties contained in IDictionary can be used to configure a channel before it’s used.

Most of the channel properties are outside the scope of this book and relate to advanced remoting operations. The only relevant property for this section is port, which applies only to server channels, those channels that can be used to publish an object service.

Here’s an example of creating a channel using the port property:

IDictionary x_props = new Hashtable();
x_props["port"] = "20172";
HttpChannel x_channel = new HttpChannel(x_props, null, null);

This is equivalent to

HttpChannel x_channel = new HttpChannel(20172);

Important

The properties of a channel are accessible via the Properties property. Changing the value of these properties has no effect on the channel configuration. Properties must be defined and passed in via the constructor.

Registering a Channel

A channel cannot be used until it’s registered. At least one channel must be registered before remoting operations can be performed. Channels are registered in the following way:

ChannelServices.RegisterChannel(mychannel);

The ChannelServices class is used to register, unregister, and locate channels. Once a channel has been registered, it becomes available for use. A channel can be withdrawn from use with the UnregisterChannel method of the ChannelServices class.

Using More than One Channel

Applications can register more than one channel; for example, a server application can offer services via HTTP and TCP. Different types of clients can have different network requirements, and the programmer can decide which channel is best suited to the task at hand.

The HttpChannel class is better suited to clients that are located on different networks. Using SOAP over HTTP makes traversing Internet proxies easier, and the HttpChannel class provides specific support for using proxies. By contrast, TcpChannel uses a binary encoding that is transmitted directly using sockets. This combination of format and transport is less likely to pass through proxies, but it does offer a performance advantage. For applications that need to offer a service to both internal and external clients, multiple concurrent channels give the best of both worlds, providing compatibility for remote clients and performance for local clients.

Here’s a variation of the Start class from the preceding example, shown without the necessary using statements, which registers both a TcpChannel and an HttpChannel. The changes are marked in boldface:

class Start {
    static void Main(string[] p_args) {
        // create the count server instance
        CountServer x_server = new CountServer();

        // create and register the channel
        HttpChannel x_channel = new HttpChannel(20172);
        ChannelServices.RegisterChannel(x_channel);

        // create the tcp channel
        TcpChannel x_tcp_channel = new TcpChannel(20173);
        ChannelServices.RegisterChannel(x_tcp_channel);

        // register the count server for remoting
        RemotingConfiguration.RegisterWellKnownServiceType(
            typeof(CountServer), "CountServer",
            WellKnownObjectMode.Singleton);

        Console.WriteLine("Press return to exit.");
        Console.ReadLine();
    }
}

We can now redefine the client-side InitRemoteServer method to use TCP as follows:

private void InitRemoteServer() {
    RemotingConfiguration.RegisterWellKnownClientType(
        typeof(CountServer), "tcp://localhost:20173/CountServer");
}

Notice that the protocol scheme for the client URL has changed to tcp. Using the HttpChannel class requires clients to use the http scheme, while the TcpChannel class requires the tcp scheme. Using the wrong scheme (for example, tcp for a URL that should map to an HttpChannel) will result in an exception at run time.

Clients with this new definition can coexist alongside the original version without any problems. The appropriate channel will receive requests, and the object that is targeted by a remote request is not aware of which protocol and transport were used.

Multiple instances of the same type of channel can also coexist, although care must be taken to ensure that the remoting system can tell them apart. This is achieved using the name property. The following example demonstrates how to create two channels of the same type with different names:

using System.Collections;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System.Runtime.Remoting.Channels.Http;

public class MultipleChannelTest {

    public MultipleChannelTest() {
        IDictionary x_props1 = new Hashtable();
        x_props1["port"] = "20174";
        x_props1["name"] = "http-20174";
        HttpChannel x_channel1 =
            new HttpChannel(x_props1, null, null);
        ChannelServices.RegisterChannel(x_channel1);

        IDictionary x_props2 = new Hashtable();
        x_props2["port"] = "20175";
        x_props2["name"] = "http-20175";
        HttpChannel x_channel2 =
            new HttpChannel(x_props2, null, null);
        ChannelServices.RegisterChannel(x_channel2);
    }

    public static void Main() {
        new MultipleChannelTest();
    }
}

Channels have a default name, which is http for instances of HttpChannel and tcp for TcpChannel. The naming scheme is left to the programmer to define; any valid string value can be used. To create multiple channels of the same type without unique names, the name property should be set to the empty string, which allows any number of channels to be registered without conflict. For clarity, however, we recommend using meaningful names.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset