Introduction
This is a sample chat application using Windows Services and .NET Remoting. It is not a full fledged chat application as you see in real world, but it does make you familiar with Windows services and .NET Remoting.
Background
.NET Remoting is widely used for implemneting inter process communication. You can use a client application that uses objects in another process on the same computer or on any other computer.
To use .NET Remoting to build an application in which two components communicate directly across an application domain boundary, you need to build only the following:
- A remotable object.
- A host application domain to listen for requests for that object.
- A client application domain that makes requests for that object.
Using the code
This sample shows you how you can have a chat server with a remotable object hosted in it and let multiple client applications share that object. This sample has three different solutions:
- RemoteHello: This is a remotable object that will be hosted by the chat server.
- ChatServer: This is the Windows service that will act as a chat server. This will also host the remotable object which will be used by multiple clients.
- ChatClient1: This is the client application which will connect to the chat server.
Steps to create this application:
- Create a remotable object: RemoteHello is a console application which has a ChatServerObject.cs class file. This class inherits
System.MarshaByRefObject
. MarshalByRefObject
is the base class for objects that communicate across application domain boundaries by exchanging messages using a proxy. Objects that do not inherit from MarshalByRefObject
are implicitly marshal by value. When a remote application references a marshal by value object, a copy of the object is passed across application domain boundaries. Build this application, and you will see RemoteHello.dll is created. Now, you need to add a reference of this RemoteHello.dll to ChatServer and ChatClient1. The reason we need to add it to ChatClient is so that the proxy of the remotable object can be created on the client side.
namespace RemoteHello
{
public class ChatServerObject : System.MarshalByRefObject
{
private ArrayList clients = new ArrayList();
private String chatSession = "";
public void AddClient(string name)
{
if (name != null)
{
lock (clients)
{
clients.Add(name);
}
}
}
public void RemoveClient(String name)
{
lock (clients)
{
clients.Remove(name);
}
}
public void AddText(String newText)
{
if (newText != null)
{
lock (chatSession)
{
if (chatSession == "")
chatSession += newText;
else chatSession +=Environment.NewLine + newText;
}
}
}
public ArrayList Clients()
{
return clients;
}
public String ChatSession()
{
return chatSession;
}
}
}
- Create a Windows service that will act as a chat server: As you create a new Windows service, you will see that two override methods are already added,
OnStart
and OnStop
. In the OnStart
method, we will select the channel we are going to use to communicate with the client. I am going to use an HttpChannel
that will use the HTTP protocol to transmit messages. After you have selected the channel and registered it, register the remotable object with this service.
protected override void OnStart(string[] args)
{
HttpChannel channel = new HttpChannel(12345);
ChannelServices.RegisterChannel(channel);
RemotingConfiguration.RegisterWellKnownServiceType(typeof(ChatServerObject),
"ChatSeverAddress", WellKnownObjectMode.Singleton);
}
As you can see, we are registering an object of type ChatServerObject
which is in our RemoteHello.dll. ChatServerAddress
is the object URI which will be used by the client to locate the service. The last parameter WellKnownObjectMode.Singleton
needs some explanation. It defines how well-known objects are activated.
Member name | Description |
---|
Singleton | Every incoming message is serviced by the same object instance. |
SingleCall | Every incoming message is serviced by a new object instance. |
Since we want to share our object with all the clients, we will make it a singleton.
Now, we need to add the installer to install this Windows service. Right click on your Windows service in Design mode and then click Add Installer. This will add ProjectInstaller.cs to your project. If you go to the Design mode of this installer, you will see two controls have already been added:
ServiceInstaller1
serviceProcessInstaller1
Set the properties like DisplayName
, Description
, ServiceName
, and AccountType
of these controls. Also, we want our service to be in Start mode when it gets installed. This can be achieved by adding a ServiceController
. So, override the Install
function in your PRojectInstaller
class like this:
public override void Install(IDictionary stateSaver)
{
base.Install(stateSaver);
ServiceController controller = new ServiceController("ChatService");
controller.Start();
}
Once we are done with it, we can use InstallUtil to install our application. So, start the Visual Studio command prompt. Change the path to the debug folder of your chat service, and then use the command as:
InstallUtil ChatService.exe
You can verify if the service was installed correctly. Go to Start-->Run--Services.msc. See if your chat service was installed. The name of the service will be the name you gave in the projectInstaller properties.
So now, we have our chat server running with a remotable object hosted in it.
- Create a client application.
Create a GUI as you like. I did not concentrate on the GUI but you can always make it look better. Here are a few things to note:
- Create an
HTTPChannel
and register it.
HttpChannel channel = new HttpChannel();
ChannelServices.RegisterChannel(channel);
- Register
wellKnownClientType
.
RemotingConfiguration.RegisterWellKnownClientType(
typeof(ChatServerObject), "http://localhost:12345/ChatSeverAddress");
- Create a proxy of the remote object hosted on the server.
_chatServerObject = new ChatServerObject();
- Create a new thread which will run an infinite
for
loop which does two things:
- Get total clients from the server.
- Get the chat text from the server.
The use of other controls on this form is very straightforward. Also make sure you run the chatClient application outside the IDE so that you can run multiple clients. Start by logging in in which will create a connection between the client and the chat server and also create a proxy of the remotable object.
History
I will work on making a more real world type chat application where you can chat with a single client instead of broadcasting the text to all the connected clients.