Channels and .NET Remoting
Gopalan Suresh Raj

Note
To work with any of these samples, you will need the following:
.........................................Microsoft .NET SDK
.........................................Microsoft Visual Studio.NET Beta 2 or higher

The .NET framework uses Channel Objects to connect Applications together. The two Channels which are available right now in the .NET framework are the System.Runtime.Remoting.Channels.TCP and the System.Runtime.Remoting.Channels.HTTP classes. 

The TCP channel is very close to DCOM and will provide the highest performance. It will typically be used to communicate between Applications on an Intranet environment. The HTTP channel uses the HTTP protocol to enable applications to communicate over the Internet.

I will illustrate this by developing a Command-Line based Publish-Subscribe Bulletin-Board Server and Client that keeps a list of messages send by multiple clients. 

Develop the Bulletin-Board Application

Messages that are sent from the client reach the Server which saves them in an internal ArrayList. These messages can at any time be retrieved from the Server.

1. Develop The Chat Server Application : Server

Experiment with using both the TCP Channels and the HTTP Channels in the Server Code.

TopicServer.cs
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
//////////////////////////////////////////////////////
/// The following example shows a Distributed Component
/// developed using C# and the .NET Framework.
///
/// author: Gopalan Suresh Raj
/// Copyright (c), 2002. All Rights Reserved.
/// URL: https://gsraj.tripod.com/
/// email: gopalan@gmx.net
///
//////////////////////////////////////////////////////
using System;
// Import the Remoting API support
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Http;
// Import Collections support
using System.Collections;

namespace Topic {
  /// <summary>
  /// A Bulletin Board Server that buffers messages
  /// </summary>
  public class Topic : MarshalByRefObject {

    /// <summary>
    /// Buffers the messages on the Bulletin Board Server
    /// </summary>
    ArrayList messageList_ = new ArrayList();

    /// <summary>
    /// Adds a new message to the Bulletin Board Server
    /// </summary>
    /// <param name="message">New message to be buffered</param>
    public void addMessage( string clientID, string message ) {
      messageList_.Add( message );
      Console.WriteLine( "From ClientID :" + clientID + ", Message Added :" + message );
    }

    /// <summary>
    /// Retrieves all messages stored on the Server
    /// </summary>
    /// <returns>All messages, each concatenated by new line characters</returns>
    public string retrieveAllMessages(string clientID) {
      string messages = null;
      foreach ( string message in messageList_ ) {
        messages += message+"\n";
      }
      return messages;
    }

    /// <summary>
    /// Displays on console any string thats pased as a parameter
    /// </summary>
    /// <param name="info">string to be displayed</param>
    /// <returns>string that was displayed</returns>
    public string displayMessage( string clientID, string info ) {
      Console.WriteLine( info );
      return info;
    }
  }

  /// <summary>
  /// The Server class implementation
  /// </summary>
  public class TheServer {

    /// <summary>
    /// Entry Point into this application
    /// </summary>
    public static void Main() {
      int listeningChannel = 1099;
      // Create a New HTTP Channel that listens on Port listeningChannel
      // TcpChannel channel = new TcpChannel( listeningChannel );
      HttpChannel channel = new HttpChannel( listeningChannel );
      // Register the channel with the runtime
      ChannelServices.RegisterChannel( channel );
      // Expose the Calculator Object from this Server
      RemotingConfiguration.RegisterWellKnownServiceType( typeof( Topic ),
                                                                                         
    "Topic",
 
                                                                                            WellKnownObjectMode.Singleton );
      // Keep the Server running until the user presses enter
      Console.WriteLine( "The Topic Server is up and running on port {0}", listeningChannel );
      Console.WriteLine( "Press enter to stop the server..." );
      Console.ReadLine();
    }
  }
}

2. Develop the Bulletin-Board Client Application : Client

In the Client Application on Line 30, The "Topic"  URI is used by the Client to identify the Server that it wanted to connect to. This matches up with the URI parameter to the RemotingServices.RegisterWellKnownServiceType() on line 78 in the Server code. Please be aware that the HTTP Channel is using soap formatted messages.

TopicClient.cs
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
//////////////////////////////////////////////////////
/// The following example shows a Distributed Component
/// Client developed using C# and the .NET Framework.
///
/// author: Gopalan Suresh Raj
/// Copyright (c), 2002. All Rights Reserved.
/// URL: https://gsraj.tripod.com/
/// email: gopalan@gmx.net
///
/// <compile>
/// csc /r:TopicServer.exe TopicClient.cs
/// </compile>
/// <usage>
/// TopicClient port
/// </usage>
//////////////////////////////////////////////////////
using System;
// Import the Remoting API support
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Http;
// Use the Topic namespace
using Topic;

namespace Topic {
  /// <summary>
  /// The Client to a Distributed Bulletin Board Server
  /// </summary>
  class TopicClient {
    static void Main(string[] args) {

      if (args.Length < 1) {
        Console.WriteLine( "\tUsage: TopicClient port" );
        Console.WriteLine( "\t e.g., TopicClient 1000" );
        return;
      }

      int listeningChannel = Int32.Parse( args [0] );
      // Create and register a channel to communicate to the server
      // The Client will use the port passed in as args to listen for callbacks
      HttpChannel channel = new HttpChannel( listeningChannel );
      ChannelServices.RegisterChannel( channel );


      // Create an instance on the remote server and call a method remotely
      Topic topic = (Topic) Activator.GetObject( typeof ( Topic ),  // type to create
                                                
                       "http://localhost:1099/Topic" // URI
                                                
                       );
      if (topic == null) {
        Console.WriteLine( "Unable to obtain a Reference to the Remote Topic Server component ..." );
        return;
      }
      // Create a unique Client ID
      string clientID = Guid.NewGuid().ToString();
      string message = "New Client ID: "+clientID+", Connected From Port "+listeningChannel;
      // Invoke a method from the Server and display the returned value
      Console.WriteLine( topic.displayMessage( clientID, message ) );
      while (message.ToLower().StartsWith( "quit" ) == false) {
        Console.WriteLine( "Enter a Message to Add to Server, 'quit' to exit application" );
        message = Console.ReadLine();
        topic.addMessage( clientID, message );
      }
      Console.WriteLine( "The Messages Are:" + topic.retrieveAllMessages( clientID ) );
      topic.displayMessage( clientID,
                                       "Client "+ clientID +
                                       ": Connected From Port "+listeningChannel+
                                       ", Terminating..." );
    }

  }
}

3. Compile the Server and the Client Applications

Command Prompt
C:\MyProjects\Cornucopia\Remoting\Topic>csc /debug+ /r:system.runtime.remoting.dll TopicServer.cs
Microsoft (R) Visual C# Compiler Version 7.00.9254 [CLR version v1.0.2914]
Copyright (C) Microsoft Corp 2000-2001. All rights reserved.


C:\MyProjects\Cornucopia\Remoting\Topic>
C:\MyProjects\Cornucopia\Remoting\Topic>
csc /debug+ /r:TopicServer.exe /r:system.runtime.remoting.dll TopicClient.cs
Microsoft (R) Visual C# Compiler Version 7.00.9254 [CLR version v1.0.2914]
Copyright (C) Microsoft Corp 2000-2001. All rights reserved.


C:\MyProjects\Cornucopia\Remoting\Topic>

4. Run One Instance of the Server (TopicServer.EXE) and Multiple Instances of the Client (TopicClient.EXE)

Remember to be connected to the Internet if you're using the HTTPChannel.

Command Prompt
C:\MyProjects\Cornucopia\Remoting\Topic>start TopicServer

C:\MyProjects\Cornucopia\Remoting\Topic>
start TopicClient 1000

C:\MyProjects\Cornucopia\Remoting\Topic>
start TopicClient 2000

C:\MyProjects\Cornucopia\Remoting\Topic>
start TopicClient 3000

C:\MyProjects\Cornucopia\Remoting\Topic>

Download the entire source code as a zip file.

 

click here to go to
My Advanced C#/.NET Tutorial Page...

About the Author...
Gopalan Suresh Raj is a Software Architect, Developer and an active Author. He has co-authored a number of books including "Professional JMS", "Enterprise Java Computing-Applications and Architecture" and "The Awesome Power of JavaBeans". His expertise spans enterprise component architectures and distributed object computing. Visit him at his Web Cornucopia© site (https://gsraj.tripod.com/) or mail him at gopalan@gmx.net.

 


Go to the Component Engineering Cornucopia page

This site was developed and is maintained by Gopalan Suresh Raj

This page has been visited times since October 19, 2000.

Last Updated : Jan 16, '02

If you have any questions, comments, or problems regarding this site, please write to me I would love to hear from you.


Copyright (c) 1997-2002, Gopalan Suresh Raj - All rights reserved. Terms of use.

All products and companies mentioned at this site are trademarks of their respective owners.