Click here to Skip to main content
15,868,016 members
Articles / Programming Languages / XML
Article

Remote Execution Using .NET Remoting

Rate me:
Please Sign up or sign in to vote.
4.50/5 (14 votes)
3 Jan 200612 min read 185.2K   3.1K   70   37
Using .NET Remoting to create a client-server application which takes advantage of using Asunchronous Callback methods.

Introduction

There are several ways to execute a process on other computers or other application domains which are related to each other through a network (LAN or Internet). Remote executing means running a process in another computer without using any resource or CPU load in the local computer. Using a client/server application is the only solution for doing so. We can create and use such applications in a wide range of platforms and methodologies. For example, we can write a client and a server program which communicate by sending and receiving network packets. In this case, we have to deal with creating sockets, passing the data packets over the network socket, and allowing the component on the server side to accept the packet, process the request, and pass the proper data back to the client component. Also, we can use DCOM (Distributed Component Object Model), which is a programming model for calling methods of objects running on a server.

Another way is using .NET Remoting which is built on the .NET Framework technology. In this case, a managed object can be accessed by a remote client. When a client makes a call to an object of the server program, a proxy object grabs the call first. The proxy object behaves like the remote object, except that the proxy object is running locally. As you may know, there is also the XML Web Services technology built on the .NET Framework which in some cases is the same as .NET Remoting. It is not very ideal to use Web Services for our task (Remote Executing).

Now, here is a question that why I have used .NET Remoting for this task? Remoting, as supported by the .NET Framework, allows applications to share class data and methods among computers on the network, similar to the concept of web services. By Remoting, class methods can be hosted on a network device and called from any CLR based program. When creating sockets, we have to worry about maintaining an open port connection. Typically, the application on the server side would register on a port and wait for incoming messages. If the client application is configured to do something special by receiving incoming messages, it's required that the incoming message be checked and verified for doing the proper task. But in .NET Remoting, we don't have to worry about maintaining the open port and also doing the extra task of verifying the incoming messages. The trouble with DCOM is that the model is intended for communication between COM objects. COM is not the technology on which the .NET Framework is built. So it missed up some great functionality and flexibility that exists in the .NET Framework.

A Brief introduction to .NET Remoting

Using the .NET Remoting architecture leads to reduction in the amount of time that you have to spend working on the networking issues. Remoting provides you with a number of choices such as configuration of the communication used. Configuration areas are the choice of channel, type of hosting application, the activation model, the configuration method, and the method of exposing the server metadata to the client application. The channel is the means of communication used by an application to call to a remote object; the selection is between HTTP and TCP. The HTTP channel which uses SOAP formatting, is mostly used for Internet communication where firewalls need to be negotiated. The TCP channel which uses binary formatting, has a performance gain by using direct socket connections over an arbitrary port selected by the developer; however, it may not be the solution for network communication through firewalls.

Remote Execution

This .NET Remoting based application includes three different programs:

  1. Server or remotable type,
  2. Listening or host application, and
  3. Client or calling application domain.

The host and the client are executable applications and use all types of application domains. The host application can even be hosted in a Windows Service and IIS (if HTTP channel is used). The server program is a class library which will be referenced in the client applications.

Building a Remote Server

The type of this remote server project is a class library. In order to enable objects in the client application to use an instance of the server class, it must be inherited from MarshalByRefObject. The following code shows the RemoteExecuteServer class declaration and the implementation:

C#
public class RemoteExecuteServer : MarshalByRefObject
{
    public void Run()
    {
       Process myProcess = new Process();
       ProcessStartInfo info = new ProcessStartInfo("notepad.exe");
       myProcess.StartInfo = info;
       myProcess.Start();
       myProcess.Close();
    }
}

The class is inherited from MarshalByRefObject and contains a method to simply run a process.

Building a Host Application

By itself, the remotable class defined above is not special. To enable objects in other application domains to create instances of this object remotely, you must build a host or listener application to choose and register a channel, and also register your type with the .NET remoting system so that it can use your channel to listen for requests for your type.

As is mentioned above, you can build host applications using different types of application domains such as Windows Forms application, an ASP.NET Web application, a console application, a Windows Service, or any other managed application domain. I use a simple Windows Form for this task. Because remote configuration is accomplished on a per-application-domain basis, the application domain must be running to listen for requests.

Here, I've created a Windows Forms application as a host application. The host application only needs to configure and register the remote server type. For doing so, I've simply put the following code to the Form_Load() method:

C#
private void Form1_Load(object sender, System.EventArgs e)
{
      RemotingConfiguration.Configure(@"..\..\REHost.exe.config");
}

The host application must be able to find the REHost.exe.config file to load the configuration for the RemoteExecuteServer class. This configuration file should be saved in the same directory as the host application exe file. Note that you have to copy the configuration file beside the host application exe file in the debug or release directory. Otherwise, you’ll therefore need to use the “..\..\” syntax in the file path to reach the configuration file in your source code directory.

The required settings for this .NET Remoting system can be achieved not only inside the code but with configuration files as well. These files are XML formatted so that they are easily readable and easily parsed by the .NET Framework. The Remoting configuration files are needed for the host and the client applications. I've created the REHost.exe.config file beside my host application.

The following code shows the REHost.exe.config configuration file for this host application domain:

XML
<configuration>
   <system.runtime.remoting>
      <application name="ReServer">
         <service>
            <wellknown 
               mode="Singleton" 
               type="ReServer.RemoteExecuteServer,ReServer" 
               objectUri="RemoteExecuteServer "
            />
         </service>
         <channels>
            <channel ref="tcp" port="8084"/>
         </channels>
      </application>
     <debug loadTypes="true" />
   </system.runtime.remoting>
</configuration>

The host application uses the information in this file to listen for and route remote requests to an instance of a remotable type. The file specifies the Singleton server-activation mode, the type name, and the assembly of the type on behalf of which it is to listen, and the object URI or external name of the object. The file also tells the Remoting system to listen for requests on port 8084 using the system-provided TcpChannel.

Building a Client Application

The client application is the last step for this demonstration. In this example, the client application will be a standard Windows application with a main form, but it could also be any other type of .NET application.

To build a client of the defined remote type which is hosted by the host application created in the previous part, my application must register itself as a client for that remote object, and then invoke it within the client's application domain. The .NET Remoting system will intercept your client calls, forward them to the remote object, and return the results to your client.

For a client program to use the class methods in the remote class, the client must know what methods are available and how to access them. The client program must be compiled with a proxy class to specify the format of the remote class methods. All references to the remote class methods are passed to the proxy class for processing. In order to create and consume that proxy class, the client application needs a reference to the remoting application’s DLL.

An object of the remote class (RemoteExecuteServer) is declared in Form1 and the related code for registration and configuration are written in the constructor of the Form1 class, as shown in the following code example:

C#
try
{
    RemotingConfiguration.Configure("REClient.exe.config");
}
catch (Exception e)
{
    // proper code
}
remObject = new RemoteExecuteServer();

Actually, the object will be created in the server and only its reference will be redirected to the client. Here in the button click event handler of the client application, I've called the Run() method from the remote server class.

C#
private void btnRun_Click(object sender, System.EventArgs e)
{
    remObject.Run();
}

As you can see in the example, the client class must be able to find the REClient.exe.config file to load the configuration for the remote class. This file should be saved in the same directory as the client executable file.

The following code example shows the REClient.exe.config configuration file for this host application domain.

XML
<configuration>
   <system.runtime.remoting>
      <application name="REClient">
         <client>
           <wellknown type="REServer.RemoteExecuteServer, REServer"
                   url="tcp://ServerName:8080/RemoteExecuteServer"/>
         </client>
        <channels>
           <channel ref="tcp"
                    port="8084"/>
        </channels>
      </application>
   </system.runtime.remoting>
</configuration>

It's better to create the above projects in one solution. After you compile the entire solution, first of all, you should run the host application, and then you can run the client application and execute a process in the server domain.

Although the above .NET Remoting application is a good start and has shown how to execute a remote process, some areas need improving in order for the application to become more flexible. One of the important features we can add is an ability to be notified from the server. Assume, we execute a process on the server domain but somehow the process gets killed, so how can we be informed about that? This will be the topic of the next issue of this article.

Notification from Server

Due to some reasons, we might want to build an event-driven Remoting application. It means the server application signals the occurrence of an action for the client application to do a special task. Here, we want to add functionality to notify the client when the process execution (executed by the client in a server domain) status is changed.

One of the solutions for doing so is using Events. In event communication, what is needed is an intermediary between the source and the receiver. The .NET Framework defines a special type called Delegate that provides the functionality of a function pointer.

If the end of the process execution is the only reason to notify the client application, we can use Asynchronous Remoting. So far, all the method invocations that are used in this example have been synchronous. In a synchronous method call, the thread that executes the method call waits until the called method finishes execution. Such types of synchronous calls can take a long time and make the other process in the client application to freeze while it is waiting for a long process to finish executing on the server. If the client is a Windows Forms application, it makes the user interface very non-responsive. An asynchronous method calls the method and returns immediately, so it leaves the invoked method to complete its execution.

Asynchronous programming like Events is implemented with the help of delegate types. Both the server and host applications that I created above no longer need additional code that supports asynchronous method calls. The asynchronous call functionality is completely dependent on the client application. So I must change my client application to be able to call a remote method asynchronously. Delegates can store references to methods. We declare a delegate and its object as follows in the client class definition. This delegate is capable of invoking methods with no parameter and return type.

C#
delegate void LongRuningProcess();
LongRuningProcess longProcess;
AsyncCallback ab;
IAsyncResult ar;

This delegate can hold references to the Run() method which is declared in the remote server class. The objects of AsyncCallback delegate and IAsyncResult interface are defined as well. AsyncCallback provides a way for client applications to complete an asynchronous operation. This callback delegate is supplied to the client when the asynchronous operation is initiated. In fact, this delegate is used to store the reference to the callback method that we want to execute when the remote execution finishes.

AsyncCallback uses the IAsyncResult interface to obtain the status of the asynchronous operation. Here, the IAsyncResult interface is used to monitor an asynchronous call and relate the beginning and the end of an asynchronous method call.

Now, we need some methods to initialize the remote server and run a remote process. For doing so, we can write the following code:

C#
public void InitRemoteServer()
{
    try
    {
           RemotingConfiguration.Configure("REClient.exe.config");
    }
    catch (Exception e)
    {
             // proper code
    }
    
    RemoteExecuteServer remObject = new RemoteExecuteServer();

    ab = new AsyncCallback(OnExitProcessExecution);

    longProcess = new LongRuningProcess(remObject.Run);
}

The above method instantiates a remote object and instantiates the AsyncCallback delegate object to hold the reference of the OnExitProcessExecution callback method which is called when the asynchronous call is completed. A LongRunningProcess delegate object is also created to hold the reference of the remote Run() method.

After we have the delegate object available, we can call its BeginInvoke() method to call the remote Run() method asynchronously, as shown here:

C#
ar = longProcess.BeginInvoke(ab, null);

Now, by running a remote process as above when the process execution is ends, the OnExitProcessExecution callback method is called so that the client application can be notified about the finishing of the remote process execution.

C#
void OnExitProcessExecution(IAsyncResult ar)
{
    longProcess.EndInvoke(ar);
}

The EndInvoke method gets the return value of the asynchronous operation represented by the IAsyncResult passed by this interface. If the asynchronous operation has not completed, this method will wait until the result is available.

Conclusion

As is stated above, there are several methods to make a connection between a server application and its clients. I described the use of .NET Remoting as a proper solution in this article. What I emphasized on throughout this article is receiving notifications from the server by clients. Although I have used the Asynchronous Callback method this is not the only way for doing so. Surely, there are different solutions that can be used other than using the Asynchronous Callback method. Using Events is one solution which you can take advantage of in your client-server applications. In this matter, you can use the proper event handlers in your client program which are called when specific tasks occur in the server program.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Software Developer (Senior)
Iran (Islamic Republic of) Iran (Islamic Republic of)
I am an independent principal software
developer and architect with nearly 20 years of
hands-on experience in the Microsoft
technology stack with a special focus on .NET
Framework (.NET Core). While working primarily
in the industrial area, I learned how to deliver
critical software systems that are highly
available, secure, and fast.
I am now a senior backend developer delivering
SaaS applications running on cloud and
on-premises. I am generally interested in Clean
Architecture, DDD, Microservices, Azure and AWS

Comments and Discussions

 
Generalunknown host Pin
V.V.Thakur29-May-06 21:50
V.V.Thakur29-May-06 21:50 
GeneralRe: unknown host Pin
Majid Shahabfar29-May-06 23:53
Majid Shahabfar29-May-06 23:53 
GeneralRe: unknown host [modified] Pin
V.V.Thakur30-May-06 2:08
V.V.Thakur30-May-06 2:08 
GeneralRe: unknown host [modified] Pin
Majid Shahabfar30-May-06 4:21
Majid Shahabfar30-May-06 4:21 
QuestionHow to dynamically connect to different servers Pin
reexmonkey4-Apr-06 4:58
reexmonkey4-Apr-06 4:58 
AnswerRe: How to dynamically connect to different servers Pin
Majid Shahabfar4-Apr-06 7:50
Majid Shahabfar4-Apr-06 7:50 
GeneralRe: How to dynamically connect to different servers Pin
reexmonkey4-Apr-06 22:29
reexmonkey4-Apr-06 22:29 
QuestionHow to compile a C# project by .ner remoting Pin
samtam1-Apr-06 1:19
samtam1-Apr-06 1:19 
AnswerRe: How to compile a C# project by .ner remoting Pin
Majid Shahabfar1-Apr-06 18:49
Majid Shahabfar1-Apr-06 18:49 
AnswerRe: How to compile a C# project by .ner remoting Pin
Jerone12-Apr-06 5:34
Jerone12-Apr-06 5:34 
Jokenice and clear Pin
saber_solomon9-Feb-06 23:47
saber_solomon9-Feb-06 23:47 
GeneralRe: nice and clear Pin
Majid Shahabfar10-Feb-06 1:17
Majid Shahabfar10-Feb-06 1:17 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.