Simple .NET Remoting Demonstration

DdoubleD 2 Tallied Votes 1K Views Share

Quite a few people have been asking how they can get their applications to talk to each other. More specifically, they have been wanting to know how to access information from another running application using .NET Remoting.

Not having done this before, I decided to take up the challenge and create a simple example of this approach. Thus, this code snippet and attached solution. I only posted relevant code in the snippet, but all projects and files can be found in the attached solution.

The SimpleServer form application runs a form having a textbox that I added some default text to, but you can change this value as you are testing the implementation of the Client form applications.

The SimpleClient1 and SimpleClient2 form applications run a form having a multiline textbox and a button to retrieve text from the SimpleServer application.

In both the SimpleServer and SimpleClient1 examples, the application loads the RemoteConfiguration settings from a configuration file. This is probably the best way to go, as it allows these settings to be modified (to change port, etc.) without the need to recompile the applications

The SimpleServer2 example has the RemoteConfiguration settings hardcoded, and demonstrates using TcpClientChannel as well as Activator.GetObject to communicate with the SimpleServer application.

Cheers!

EDIT: Note that I don't have more than one machine, so I could only perform local machine tests. If you try this on two machines, you will need (at a minimum) to adjust the SimpleServer.config file by removing the "rejectRemoteRequests" option, or setting it to "false".

<channel ref="tcp" port="33000" rejectRemoteRequests="false"/>
ddanbe commented: Great! +4
///////////////////////////////
// SimpleServer Project
///////////////////////////////

//////////////// Program.cs ///////////////////////////////////////////////

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using System.Runtime.Remoting;

namespace SimpleServer
{
    static class Program
    {
        // Property to allow service to retrieve a reference to SimpleService's form...
        internal static Form_SimpleServer FormSimpleServer { get; set; }

        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            // Setup the server configuration from file...
            // NOTE: Configuring this way allows reconfiguration without the need to recompile...
            RemotingConfiguration.Configure("SimpleServer.config", false);

            // Create form object and run...
            FormSimpleServer = new Form_SimpleServer();
            Application.Run(FormSimpleServer);
        }
    }
}

////////////// SimpleServer.config /////////////////////////////////////

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.runtime.remoting>
    <application>
      <service>
        <wellknown
          type="SimpleServer.MyService, SimpleServer"
          objectUri="MyServiceUri"
          mode="SingleCall" />
      </service>
      <channels>
        <channel ref="tcp" port="33000" rejectRemoteRequests="true"/>
      </channels>
    </application>
  </system.runtime.remoting>
</configuration>

////////////// MyService.cs //////////////////////////////////////////////

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SimpleServer
{
    // Interface to access service methods...
    public interface IMyServiceInterface
    {
        string GetTextBoxText();
    }

    /* 
     * MyService: Service class that inherits MarshallByRefObject
     * 
     * MarshalByRefObject MSDN Definition: Enables access to objects across 
     *      application domain boundaries in applications that support remoting.
     */
    public class MyService : MarshalByRefObject, IMyServiceInterface
    {
        // exposed interface method to retrieve contents of textbox...
        public string GetTextBoxText()
        {
            return Program.FormSimpleServer.GetTextBoxText();
        }
    }
}

/////////////// Form_SimpleService.cs /////////////////////////////////

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace SimpleServer
{
    public partial class Form_SimpleServer : Form
    {
        public Form_SimpleServer()
        {
            InitializeComponent();
        }

        // method called by the service interface to retrieve textbox text...
        internal string GetTextBoxText()
        {
            return textBox1.Text;
        }
    }
}

////////////////////////////////
// SimpleClient1 Project
////////////////////////////////

//////////////// Program.cs ///////////////////////////////////////////////

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using System.Runtime.Remoting;

namespace SimpleClient1
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            // Setup the server configuration from file...
            // NOTE: Configuring this way allows reconfiguration without the need to recompile...
            RemotingConfiguration.Configure("SimpleClient1.config", false);

            Application.Run(new Form_SimpleClient1());
        }
    }
}

//////////////// SimpleClient1.config /////////////////////////////////////

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.runtime.remoting>
    <application>
      <client>
        <wellknown
          type="SimpleServer.MyService, SimpleServer"
          url="tcp://localhost:33000/MyServiceUri" />
      </client>
    </application>
  </system.runtime.remoting>
</configuration>

/////////////// Form_SimpleClient1.cs //////////////////////////////////

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.Remoting;

namespace SimpleClient1
{
    public partial class Form_SimpleClient1 : Form
    {
        // Service interface...
        SimpleServer.IMyServiceInterface iService; 

        public Form_SimpleClient1()
        {
            InitializeComponent();

            // Create interface object...
            iService = new SimpleServer.MyService();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            // access method (get text from running service form)...
            textBox1.AppendText(iService.GetTextBoxText() + "\n");
        }
    }
}

///////////////////////////////
// SimpleCllient2 Project
///////////////////////////////

///////////////// Project.cs //////////////////////////////////////////////

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;

namespace SimpleClient2
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form_SimpleClient2());
        }
    }
}

////////////////// Form_SimpleClient2.cs /////////////////////////////

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System.Security.Permissions;
using SimpleServer;

namespace SimpleClient2
{
    /// <summary>
    /// Most of the TcpClientChannel code was taken directly from MSDN Example:
    /// http://msdn.microsoft.com/en-us/library/system.runtime.remoting.channels.tcp.tcpclientchannel.aspx
    /// </summary>

    [SecurityPermission(SecurityAction.LinkDemand)]
    public partial class Form_SimpleClient2 : Form
    {
        IMyServiceInterface remoteObject;

        public Form_SimpleClient2()
        {
            InitializeComponent();

            // Set up a client channel.
            TcpClientChannel clientChannel = new TcpClientChannel();
            ChannelServices.RegisterChannel(clientChannel, false);

            // Obtain a proxy for a remote object...
            // NOTE: Doing it this way requires a recompile if changing port, etc.
            RemotingConfiguration.RegisterWellKnownClientType(
                typeof(IMyServiceInterface), "tcp://localhost:33000/MyServiceUri");

            // Obtain object reference to service interface...
            remoteObject = (IMyServiceInterface)Activator.GetObject(typeof(IMyServiceInterface), "tcp://localhost:33000/MyServiceUri");
        }

        private void button1_Click(object sender, EventArgs e)
        {
            // access method (get text from running service form)...
            textBox1.AppendText(remoteObject.GetTextBoxText() + "\n");
        }
    }
}
DdoubleD 315 Posting Shark

I was about to close some browser windows and thought I would post some links I found helpful on this topic:

Remoting_Architecture
.NET Remoting Use-Cases and Best Practices
All you need to know about .NET Remoting
.NET Remoting with an easy example

I suppose I should have added C# to the Tags entry, which I did originally but then removed it due to the limitation of six entries, but then wound up with four entries anyway due to limitations of the 20 char length... Anyway, if anyone knows how I can add "C#" to the Tags, let me know--thanks.

EDIT: I should also point out that I put the service interface directly into the SimpleServer.exe. If you prefer to use a class library (DLL) instead for this purpose, this can easily be achieved.

ddanbe 2,724 Professional Procrastinator Featured Poster

I added the tag C#. Seems to pose no problems.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.