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 2.0 that provides components for various communication scenarios.
(Full, not limited and for non-commercial usage free version of the framework 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.

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.

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.

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:


推荐.NET配套的通用数据层ORM框架:CYQ.Data 通用数据层框架
新浪微博粉丝精灵,刷粉丝、刷评论、刷转发、企业商家微博营销必备工具"