Click here to Skip to main content
15,890,506 members
Articles / Programming Languages / C#

Request-Response Communication

Rate me:
Please Sign up or sign in to vote.
5.00/5 (2 votes)
28 May 2011CPOL1 min read 17.3K   144   9   1
Simple example showing how to implement the request-response communication between applications.

Introduction

The request-response communication is a communication scenario where messages flow in both directions - request messages from the sender to the receiver and response messages from the receiver back to the sender.

The example below shows the server receiving messages and sending responses back to the client. It also shows how to implement the client sending messages to the server and receiving response messages.

The example is based on the Eneter Messaging Framework that provides components for various communication scenarios.
(The framework is free and can be downloaded from http://www.eneter.net. The online help for developers can be found at http://www.eneter.net/OnlineHelp/EneterMessagingFramework/Index.html.)

1. Define Message Types

For the request-response communication, you must define type of the request message and type of the response message.
And same as described in the previous part, you should consider what serialization will be used.
(Because the serialization can require some additional attributes in the declarations.)

In our example, we will use the binary serialization. The request message type is 'Person' and the response type is the string.

C#
using System;

namespace CommonTypes
{
    [Serializable]
    public class Person
    {
        public string Name { get; set; }
        public int NumberOfItems { get; set; }
    }
}

2. Implement the Server

The server below receives the message type of 'Person' and sends back a simple response message type of string.

C#
using System;
using CommonTypes;
using Eneter.Messaging.DataProcessing.Serializing;
using Eneter.Messaging.EndPoints.TypedMessages;
using Eneter.Messaging.MessagingSystems.MessagingSystemBase;
using Eneter.Messaging.MessagingSystems.NamedPipeMessagingSystem;

namespace DuplexTypedMessageServer
{
    class Program
    {
        // Duplex typed message receicer that receives type Person and responses type string.
        static IDuplexTypedMessageReceiver<string, Person> myMessageReceiver;

        static void Main(string[] args)
        {
            // Create factory to create input channel based on Named Pipes
            IMessagingSystemFactory aMessagingSystemFactory = new NamedPipeMessagingSystemFactory();
            IDuplexInputChannel anDuplexInputChannel =
                aMessagingSystemFactory.CreateDuplexInputChannel("//127.0.0.1/MyPipeName3");

            // Create duplex typed message receiver using the binary serialization.
            ISerializer aSerializer = new BinarySerializer();
            IDuplexTypedMessagesFactory aDuplexTypedMessagesFactory =
                new DuplexTypedMessagesFactory(aSerializer);
            myMessageReceiver = aDuplexTypedMessagesFactory.CreateDuplexTypedMessageReceiver<string, Person>();
            myMessageReceiver.MessageReceived += OnMessageReceived;

            // Attach the input channel to the string message receiver and start listening.
            myMessageReceiver.AttachDuplexInputChannel(anDuplexInputChannel);

            Console.WriteLine("The service is listening. Press enter to stop.\n");
            Console.ReadLine();

            myMessageReceiver.DetachDuplexInputChannel();
        }

        static void OnMessageReceived(object sender, TypedRequestReceivedEventArgs<Person> e)
        {
            Console.WriteLine("Received Message:");
            Console.WriteLine("Name: " + e.RequestMessage.Name);
            Console.WriteLine("Number of items: " + e.RequestMessage.NumberOfItems.ToString());
            Console.WriteLine();

            // As a response send the current time.
            string aResponseMessage = DateTime.Now.ToString();
            myMessageReceiver.SendResponseMessage(e.ResponseReceiverId, aResponseMessage);
        }
    }
}

3. Implement the Client

The client below sends the message type of 'Person' and receives the response message type of string.

C#
using System;
using System.Windows.Forms;
using CommonTypes;
using Eneter.Messaging.DataProcessing.Serializing;
using Eneter.Messaging.EndPoints.TypedMessages;
using Eneter.Messaging.MessagingSystems.MessagingSystemBase;
using Eneter.Messaging.MessagingSystems.NamedPipeMessagingSystem;

namespace DuplexTypedMessageClient
{
    public partial class Form1 : Form
    {
        // Duplex typed message sender that sends type Person and
        // receives responses of type string.
        private IDuplexTypedMessageSender<string, Person> myMessageSender;

        public Form1()
        {
            InitializeComponent();

            OpenConnection();
        }

        private void OpenConnection()
        {
            // Create factory to create input channel based on Named Pipes
            IMessagingSystemFactory aMessagingSystemFactory = new NamedPipeMessagingSystemFactory();
            IDuplexOutputChannel anOutputChannel =
                aMessagingSystemFactory.CreateDuplexOutputChannel("//127.0.0.1/MyPipeName3");

            // Create duplex typed message sender that uses the binnary serializer.
            ISerializer aSerializer = new BinarySerializer();
            IDuplexTypedMessagesFactory aDuplexTypedMessagesFactory =
                new DuplexTypedMessagesFactory(aSerializer);
            myMessageSender = aDuplexTypedMessagesFactory.CreateDuplexTypedMessageSender<string, Person>();
            myMessageSender.ResponseReceived += OnResponseReceived;

            // Attach duplex output channel and be able to send messages
            // and receive response messages.
            myMessageSender.AttachDuplexOutputChannel(anOutputChannel);
        }

        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            // Correctly close connection.
            // Otherwise the thread listening to response messages will leak.
            myMessageSender.DetachDuplexOutputChannel();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            // Prepare the message.
            Person aPerson = new Person();
            aPerson.Name = NameTextBox.Text;
            aPerson.NumberOfItems = int.Parse(NumberOfItemsTextBox.Text);

            // Send the message.
            myMessageSender.SendRequestMessage(aPerson);
        }

        private void OnResponseReceived(object sender, TypedResponseReceivedEventArgs<string> e)
        {
            string aResponseMessage = e.ResponseMessage;
            InvokeInUIThread(() => ReceivedResponseTextBox.Text = aResponseMessage);
        }

        // Helper method to invoke the given delegate
        // in the UI thread.
        private void InvokeInUIThread(Action action)
        {
            if (InvokeRequired)
            {
                Invoke(action);
            }
            else
            {
                action();
            }
        }
    }
}

And here are communicating applications:

RequestResponseApplications.jpg


License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect
Slovakia Slovakia
My programming path started in 1987 when I got my first computer Sharp MZ-800.
It came with 8 bit CPU Z80, 64Kb RAM and the tape recorder. It was a great machine. I think I still have it somewhere.
I was fascinated and I started to write first programs. Eventually I became developer and software architect. I like innovations and clean nice solutions.

Comments and Discussions

 
GeneralMy vote of 5 Pin
Filip D'haene30-May-11 2:37
Filip D'haene30-May-11 2:37 

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.