Operating Systems / Project 9- .NET Remoting in C#
Name ______Score ______
In this laboratory exercise you will build and implement a Server and a Client that will enable the execution of a program from a remote machine.
There are several different ways you can do remoting; you can marshall by value or by reference, you can use server-side activation or client-side activation. You can choose SingleCall or Singleton instantiation, among others. You can use either of the default protocols (tcp or http) or you can use a custom protocol.
The scenario we'll look at is one where we marshall by reference, use server-side activation, and Singleton instantiation. We will use TCP but this approach is equally applicable to the HTTP communication protocol. Our example will consist of three separate components:
(1) ServerApp - The ServerApp component will be the actual application containing your business logic, which you want to be able to access remotely.
(2) Listener - The Listener component will reside with the ServerApp component on the remote server.
(3) ClientApp - Its App.config file (compiled to ClientApp.exe.config) will contain information telling it the location and port of the Listener component, as well as the formatter to use (tcp or http) and how to instantiate the ServerApp.
When the server is called, the ClientApp component uses this information to contact the Listener and request an instance of the ServerApp.
Getting Started
We are going to build a Visual Studio Solution. If you are unfamiliar with this type of project, go to New under the File menu and choose New Project...In the dialog box that pops up scroll down to Other Project Types, expand and select Visual Studio Solutions. Name your solution Remoting. This will build an empty Solution. You may want to close the Start Page at this point.
Creating ServerApp
Create a new ClassLibrary project and name it ServerApp. in order to do this you will need to right-click the Solution in the Solution Explorer pane and choose New Project. Rename the default class from Class1.cs to ServerClass.cs, then replace any existing code in that file with the following:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace ServerApp
{
publicclassServerClass : MarshalByRefObject
{
publicstring Capitalize(String asData)
{
string lsRet = null; try
{
lsRet = "Capitalize returning " + asData.ToUpper()
+ " at " + DateTime.Now + " from "
+ Directory.GetCurrentDirectory();
}
catch (Exception ex)
{
Console.Write(ex.Message);
Console.Write(ex.StackTrace);
}
return lsRet;
}
}
}
The class inherits from MarshalByRefObject, which it must do in order to be remotely instantiated and marshalled by reference. ServerClass has one method, Captialize, which accepts one string argument. The class then takes that argument, converts it to upper case, embeds it in a string which also contains the date and time and the location of the ServerApp component, and if no exceptions are raised along the way, returns that string.
Creating Listener
Next we will create the Listener component. In Visual Studio, within the same Remoting solution in which we created the ServerApp project, create another new project. This one will be a Windows Forms Application, and we can name it Listener. Rename Form1.cs to FormListener.cs, and add a button to the form. Name the button btnStop, and assign "Stop Server" as its Text property. Double click anywhere on the form to load the code behind file. In the FormListener_Load event, copy the following code:
privatevoid FormListener_Load(object sender, EventArgs e)
{
try
{
RemotingConfiguration.Configure(
Assembly.GetExecutingAssembly().GetName().Name +
".exe.config", false);
}
catch (Exception ex)
{
Console.WriteLine("ERROR - " + DateTime.Now + "... " +
ex.ToString());
}
}
The first argument being passed to it represent the name of the config file to load, in this case "Listener.exe.config". (Your App.config file will take this name when your application is built.) The second argument is a boolean argument that tells the method whether to implement security or not. For our purposes we will not, so we pass false. In order for this to compile, you will also need to add the following using statements:
using System.Runtime.Remoting;
using System.Reflection;
Next, double click on the Stop Server button so that the btnStop_Click event is displayed. Then copy the following code into the event:
privatevoid btnStopTCP_Click(object sender, EventArgs e)
{
Application.Exit();
}
Next, we need to add the App.config file. In order for it to work properly, it needs to be created not as a regular text file, but as follows:
- Right-click on the Listener project
- Click Add
- Click New Item
- Choose Application Configure File from the dialog box, making sure that the file is named App.config.
Open the newly created App.config file, copy the following code into it, and then save it:
<?xmlversion="1.0"encoding="utf-8" ?>
configuration
system.runtime.remoting
application
service
wellknownmode="Singleton"
type="ServerApp.ServerClass, ServerApp"
objectUri="ServerClass"
</wellknown
</service
channels
channelref="tcp"port="1234" />
</channels
</application
</system.runtime.remoting
</configuration
Note that the channel element has a ref attribute and a port attribute. As illustrated, the settings will cause the Listener to listen for a tcp request on port 1234. If you wanted to use http instead, you would just change the ref attribute to "http".
Finally, build the entire solution. Once everything is built, create a new directory on your hard drive called "C:\RemoteTest".
Into this directory you will need to copy the following three files from your build:
- Listener.exe
- Listener.exe.config
- ServerApp.dll
Creating ClientApp
Now create one more Windows Forms Application project in our Remoting solution, called ClientApp.
Add a reference to the ServerApp application. Right-click the newly created ClientApp project, click Add Reference, and in the Add Reference dialog box, click the Browse tab. Browse to "C:\RemoteTest\ServerApp.dll", and choose it.
Next, rename Form1.cs to FormClient.cs. Then add a text box and two buttons. Name the text box txtData, and name the two buttons btnSubmit and btnExit. Open the code behind Form1(FormClient) and add the following using statements:
using ServerApp;
using System.Runtime.Remoting;
using System.Reflection;
Next, add the following variables to FormClient (at the class level):
ServerClass server;
string result;
Next, double-click anywhere on the form so that the FormClient_Load event is displayed. Then copy the following code into that event:
privatevoid FormClient_Load(object sender, EventArgs e)
{
try
{
RemotingConfiguration.Configure(
Assembly.GetExecutingAssembly().GetName().Name +
".exe.config", false);
MessageBox.Show("Channel created and client registered.");
server = new ServerClass();
}
catch (Exception ex)
{
MessageBox.Show("Unable to connect to remote object.",
"Error",
MessageBoxButtons.OK, MessageBoxIcon.Error);
Console.WriteLine("Message " + ex.Message);
Console.WriteLine(ex.StackTrace);
}
}
Next, double-click on the btnSubmit button and copy the following code into the btnSubmit_Click event:
privatevoid btnSubmit_Click(object sender, EventArgs e)
{
try
{
result = server.Capitalize(txtData.Text);
MessageBox.Show("Server returned: '" + result + "'.", "SUCCESS",
MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch (Exception ex)
{
MessageBox.Show("Error Occured: " + ex.Message, "Error",
MessageBoxButtons.OK, MessageBoxIcon.Error);
Console.WriteLine(ex.ToString());
}
}
Double-click on the btnExit control so that the btnExit_Click event is displayed, and copy the following code into it:
privatevoid btnExit_Click(object sender, EventArgs e)
{
Application.Exit();
}
Next, we need to add the client's App.config file. In order for it to work properly, it needs to be created not as a regular text file, but as follows:
- Right-click on the ClientApp project
- Click Add
- Click New Item
- Choose Application Configure File from the dialog box, making sure that the file is named App.config.
Open the newly created App.config file, copy the following code into it, and then save it:
<?xmlversion="1.0"encoding="utf-8" ?>
configuration
system.runtime.remoting
applicationname="ClientApp"
client
wellknownmode="Singleton"
type="ServerApp.ServerClass, ServerApp"
url="tcp://localhost:1234/ServerClass"
</wellknown
</client
channels
channelref="tcp" />
</channels
</application
</system.runtime.remoting
</configuration
Note also that if you wanted to use http instead of tcp, you would need to change the channel element's ref attribute, and the wellknown element's url attribute accordingly. Now you can build your ClientApp project.
Putting It All Together
In order to test all of our components, perform the following steps:
- Close Visual Studio.
- Go to C:\RemoteTest, and run Listener.exe
- Run your ClientApp.exe
- Enter any text into the ClientApp's text field
- Click the Submit button
You should see a message box containing the string returned from the server, which should include an upper case version of the text string you entered, the date and time, and the directory in which the ServerApp component resides.
Your goal for this project is to move the ServerApp and associated files to a different machine than the one running the ClientApp and Execute remotely. After you have successfully accomplished a remote execution answer the question below:
Questions
1. How did you change the configuration file associated with the ClientApp? Specifically give your version of the line:
url="tcp://localhost:1234/ServerClass"
______
2. Describe the differences between the client-side and server-side configuration files.
______
______
______
3. In the FormClient_Load( ) method, explain the purpose and operation of the statement:
RemotingConfiguration.Configure(
Assembly.GetExecutingAssembly().GetName().Name +
".exe.config", false);
______
______
______