In my networking class this term, we built a simple chat program. It’s nothing
fancy – type in your name, a server, and see what others are posting.
I decided to learn a little bit about .NET Remoting in this exercise. I found
numerous examples (including some chat programs) demonstrating how easy it was
to create such a program and felt confident with choice I had made. The only
thing I had to add to the consolidation of information I had found was a way
to select the server one was using.
Yeah… just that.
Now, it’s entirely possible that I missed some nugget of information out there
and even that there is a different (better?) way of doing this, but I think I
learned something of value through this exercise.
First, the app.config
file I was using that worked fine was as follows:
<?xml
version="1.0"
encoding="utf-8"
?>
<configuration>
<system.runtime.remoting>
<application>
<client>
<wellknown
url=http://ServerName:7777/LeChat
type="LeChat.Broker.LeChatBroker, LeChatBroker"
/>
</client>
<channels>
<channel
ref="http"
name="client"
port="8888"
>
<clientProviders>
<formatter
ref="soap" />
</clientProviders>
<serverProviders>
<formatter
ref="soap"
typeFilterLevel="Full" />
</serverProviders>
</channel>
</channels>
</application>
</system.runtime.remoting>
</configuration>
With this file, one only has to load the settings with:
RemotingConfiguration.Configure( "AppName.exe.config" );
Easy! Of course, if I want to change the name of my server, what do I do?
Some of the learning I had:
The app.config file is meant to be a
quasi-read-only file. Although one can write to it through various means, it
is loaded at the launch of the application and cached for use throughout the
activation – once the program is running, changing the
app.config would make no difference.
All of the examples I found for loading the configuration in code were nearly
identical:
HttpChannel channel = new HttpChannel( 8888 );
ChannelServices.RegisterChannel( channel );
RemotingConfiguration.RegisterWellKnownServiceType(
typeof( LeChat.Broker.LeChatBroker ),
"http://" + serverName + ":7777/LeChat",
WellKnownObjectMode.Singleton );
This did not provide all of the parameters needed to make the two-way
communication possible between the client and the server. In fact, kept going
back and forth between having the chat text show up only on the server, or only
on the client – depending on whether I registered a …
ServiceType, or a …
ClientType. Aarrrggghhh!
Finally, I started looking at the overridden constructor on the
HttpChannel. I saw something about a
IDictionary of ‘properties’ and realized I might be
on to something. I started reading about SinkProvider’s
and felt even closer. Finally, I had constructed the complete block of code that allowed
my little chat program to work and I could insert any server name I needed to:
IDictionary configurationProperties = new Hashtable();
IDictionary serverSinkProviderProperties = new Hashtable();
configurationProperties.Add( "ref", "http" );
configurationProperties.Add( "name", "client" );
configurationProperties.Add( "port", "0" );
serverSinkProviderProperties.Add( "ref", "soap" );
serverSinkProviderProperties.Add( "typeFilterLevel", "Full" );
SoapClientFormatterSinkProvider clientSinkProvider =
new SoapClientFormatterSinkProvider();
SoapServerFormatterSinkProvider serverSinkProvider =
new SoapServerFormatterSinkProvider(
serverSinkProviderProperties, null );
HttpChannel channel = new HttpChannel(
configurationProperties,
clientSinkProvider,
serverSinkProvider );
ChannelServices.RegisterChannel( channel );
RemotingConfiguration.RegisterWellKnownClientType(
typeof( LeChat.Broker.LeChatBroker ),
"http://" + serverName + ":7777/LeChat" );
This turned out to be a more substantial investment than I had expected. I did
get a chance to learn more about how this stuff works and I’m looking forward to
reading Ingo
Rammer’s book "
Advanced .NET Remoting" to learn more. However, I felt compelled to document
what I did so that I can re-learn it all if needed.